簡體   English   中英

N次匹配特定字符后,如何匹配新行?

[英]How can I match a new line after N times for a specific char?

我正在嘗試匹配類似CSV的文件上的所有新行。 問題是大文件總是帶有一些虛線,例如:

123|some string field|person 123|some optional open comment|324|213
133|some string field|person||324|213
153|some string field|person 123|some comment|324|213
126|some string field|another id|some open and
new line comment|324|213
153|string field|person 123|some comment|324|213
153|string field|person 123|another broken line
comment|324|213
133|field|person||324|213

因此,為了解決這種情況,我使用了以下邏輯:

    string ZSUR = File.ReadAllText(filePath);
    string originalFilePath = filePath;

    // Regular Expression to fix line break issues
    Regex RE = new Regex(@"[\r\t\n]+([^0-9\r\t\n]{3}[^|\r\t\n])");

    ZSUR = RE.Replace(ZSUR, "$1");

    // Backup the original file
    string[] backupFilePath = Regex.Split(filePath, @".txt$");
    File.Delete(backupFilePath[0] + "_BACKUP.txt");
    File.Move(originalFilePath, backupFilePath[0] + "_BACKUP.txt");

    // And then save on the same path the fixed file
    File.WriteAllText(originalFilePath, ZSUR);

解決了90%的情況,因為正確行的第一部分始終以三位數字開頭,后接管道。

但是我不知道為什么它與這樣的情況不匹配:

126|some string field|another id|some open and
double newlined 
123 coment|324|213
153|some string field|person 123|some comment|324|213
153|some string field|person 123|some comment|324|213
153|string field|person 123|Please split this line
31 pcs: 05/03/2013
31|324|213
153|some string field|person 123|some comment|324|213

如您所見,我需要一種不同的方法來解決此問題。 我知道經過N次管道之后,就會出現煩人的評論字段。 那么,有什么方法可以匹配從行首開始的N個管道之后的所有新行和類似行?

也歡迎其他想法。

編輯:謝謝你們的答案。

我使用以下正則表達式解決了這個問題:

(?<!\|[CA]?\|([0-9]{2}.[0-9]{2}.[0-9]{4})?)[\n\r]+

當然,我的真實文件與發布的示例略有不同,但是主要思想是匹配所有新行[\\ n \\ r] +,而這些新行之前沒有

(?<! ... ) 

表達。

您可以像這樣處理所有事情,其中​​“ Clean”是您定義的方法。

var prev = string.Empty;
const int requiredValueCount = 6;

foreach (var line in lines2.Split(new[] {Environment.NewLine}, StringSplitOptions.None))
{
    var values = (prev + line).Split('|');

    if (values.Length == requiredValueCount)
    {
        prev = string.Empty;
        Clean(values);
    }
    else
    {
        prev += line;
    }
}

首先將所有(\\ | \\ d + \\ n)替換為\\ | \\ d ~~

然后加入所有行,刪除\\ n

然后分開~~

我不會不必要地重新發明輪子。 嘗試使用Sebastien Lorion的Fast CSV Reader 它很可能會做您需要做的事情(或為您提供對錯誤采取糾正措施的便利)。 我用過這個閱讀器,它的功能相當不錯。

另一個選擇是Codeplex的KBCsv 從未使用過,但是可能很好。

我還將采用將文件原樣讀取到記錄列表中的方法。 由於似乎不需要多一點的先行/后向查找,因此您可以在文件的一次傳遞中輕松完成此操作,如下所示:

public IEnumerable<string[]> ReadRecordsFromCSV()
{
  string[] prev = null ;
  string[] curr = null ;

  // read each individual record from the file
  while ( null != (curr=MyCsvReader.ReadRecord()) )
  {

    if ( prev == null )
    { // no previous record? just shift and continue
      prev = curr ;
    }
    else
    { // previous record? splice if needed and emit a record
      string[] record ;
      bool spliceNeeded = CheckForSpliceConditions(prev,curr) ;

      if ( spliceNeeded )
      { // splice needed? build the record to emit and clear the previous record
        record = Splice( prev , curr ) ;
        prev = null ;
      }
      else
      { // no splice needed? set the record to emit and shift
        record = prev ;
        prev = curr ;
      }

    }

    // emit the record
    yield return record ;
  }

  // emit the last record if there is one.
  if ( prev != null )
  {
    yield return prev ;
  }

}

如果您需要一個以上的先行/后向查找,則需要類似移位寄存器的功能,在其中將記錄添加到列表的末尾,然后將它們從列表的開頭除去。 您可以將List<string[]>用作此類移位寄存器,盡管這樣做有點麻煩。

編輯以注意:另一種方法(也是更簡單的方法),如果需要拼接,只需將當前記錄追加到先前的記錄,直到不再需要拼接為止。 一旦成立,就會發出先前的記錄,並且從頭開始,因此:

public IEnumerable<string[]> ReadRecordsFromCSV()
{
  string[] prev = null ;
  string[] curr = null ;

  // read each individual record from the file
  while ( null != (curr=MyCsvReader.ReadRecord()) )
  {

    if ( prev == null )
    { // no previous record? just shift and continue
      prev = curr ;
    }
    else
    { // previous record? splice if needed and emit a record
      bool spliceNeeded = CheckForSpliceConditions(prev,curr) ;

      if ( spliceNeeded )
      { // splice needed? build the record to emit and clear the previous record
        prev = Splice( prev , curr ) ;
      }
      else
      { // no splice needed? set the record to emit and shift
        yield return prev ;
        prev = null ;
      }

    }

  }

  // emit the last record if there is one.
  if ( prev != null )
  {
    yield return prev ;
  }

}

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM