2

我正在使用正则表达式来解析类似 CSV 的文件。我是正则表达式的新手,虽然它可以工作,但当有很多字段并且其中一个字段包含非常长的值时,它会变得很慢。我该如何优化它?

我必须解析的 CSV 具有以下特点:

  1. 所有字段都是用逗号分隔的引号括起来的字符串
  2. 字段内的引号以两个连续引号的形式进行转义
  3. 在一些需要忽略的行的开头有不可预测的垃圾(到目前为止它不包含引号,谢天谢地)
  4. 零长度字段和字段中的换行符是可能的

我正在使用 VB.NET。我正在使用以下正则表达式:

(^(?!").+?|^(?="))(?<Entry>"(",|(.*?)"(?<!((?!").("")+)),))*(?<LastEntry>"("$|(.*?)"(?<!((?!").("")+))$))

我通过将 StreamReader.ReadLine's 输入字符串变量来处理换行符,直到正则表达式成功,用空格替换换行符(这对于我的目的来说是可以的)。然后我使用 Match.Groups("Entry").Captures 和 Match.Groups("LastEntry") 提取字段内容。

我想性能影响来自对转义引号的后视。有没有更好的办法?

感谢您的任何想法!

4

1 回答 1

1

我认为您的正则表达式不必要地复杂,并且嵌套的量词会导致灾难性的回溯。尝试以下操作:

^[^"]*(?<Entry>(?>"(?>[^"]+|"")*"),)*(?<LastEntry>(?>"(?>[^"]+|"")*"))$

解释:

^                 # Start of string
[^"]*             # Optional non-quotes
(?<Entry>         # Match group 'entry'
 (?>              # Match, and don't allow backtracking (atomic group):
  "               # a quote
  (?>             # followed by this atomic group:
   [^"]+          # one or more non-quote characters
  |               # or
   ""             # two quotes in a row
  )*              # repeat 0 or more times.
  "               # Then match a closing quote
 )                # End of atomic group
 ,                # Match a comma
)*                # End of group 'entry'
(?<LastEntry>     # Match the final group 'lastEntry'
 (?>              # same as before
  "               # quoted field...
  (?>[^"]+|"")*   # containing non-quotes or double-quotes
  "               # and a closing quote
 )                # exactly once.
)                 # End of group 'lastEntry'
$                 # End of string

这也应该适用于整个文件,因此在正则表达式匹配之前,您不必在下一行之后添加一行,并且您不必替换换行符:

Dim RegexObj As New Regex("^[^""]*(?<Entry>(?>""(?:[^""]+|"""")*""),)*(?<LastEntry>(?>""(?:[^""]+|"""")*""))$", RegexOptions.Multiline)
Dim MatchResults As Match = RegexObj.Match(SubjectString)
While MatchResults.Success
    ' now you can access MatchResults.Groups("Entry").Captures and
    ' MatchResults.Groups("LastEntry")
    MatchResults = MatchResults.NextMatch()
End While
于 2013-07-19T09:02:02.720 回答