C#原样字符串的正则表达式(处理类似""的转义字符)

5
我正在尝试从rc文件中提取信息。在这些文件中,字符串中的"字符被双倍转义(" "),类似于C#的verbatim strings。是否有一种方法来提取字符串?
例如,如果我有以下字符串"this is a ""test""",我想获得this is a ""test""。它还必须是非贪婪的(非常重要)。
我尝试使用以下正则表达式;
"(?<text>[^""]*(""(.|""|[^"])*)*)"

然而性能很糟糕。我已经基于这里的解释:http://ad.hominem.org/log/2005/05/quoted_strings.php。有人用正则表达式应对过这个问题吗?

不,我使用C#。(我了解Perl并经常使用它,但我不能在这个应用程序中使用它) - MartenBE
那么为什么这里有Perl标签呢? :D - Martin Ender
因为我认为它与Perl正则表达式有关。如果造成任何误解,我很抱歉。 - MartenBE
1
@m.buettner "实际上比Perl更强大" - 你在挑起争端。 - tylerl
@tylerl 正在考虑...平衡组可能比递归更强大(从理论上讲),因为你有多个堆栈。我认为在.NET中,你可以匹配类似于(a) (b) (c) abc(对于任意数量的字符),而使用递归只能对(a) (b) (c) cba这样的情况进行匹配。 - Martin Ender
显示剩余3条评论
5个回答

5
你有一些嵌套的重复量词。这可能对性能造成灾难性影响。 尝试使用以下代码:
(?<=")(?:[^"]|"")*(?=")

现在只能同时使用两个引号或非引号字符。回顾先行断言和后发断言,实际匹配的内容必须在引号前面和后面。
这也避免了必须捕获任何内容的问题。您想要的结果将仅是您想要的完整字符串(不包括外部引号)。
我不确定外部引号是否重复。因为如果它们重复了,就没有办法将其与空字符串区分开来。

2
这其实比你想象的要简单得多。带有转义引号的字符串字面量看起来就像是一堆简单的字符串字面量连在一起:
"Some ""escaped"" quotes"

"Some " + "escaped" + " quotes"

所以这就是你需要匹配它的所有内容:
(?:"[^"]*")+

你需要在单独的步骤中去掉开头和结尾的引号,但这不是什么大问题。无论如何,你都需要另一个步骤来取消转义的引号 (\""")。


0
  • 匹配以双引号开始的字符串
  • 多次匹配非双引号或两个反斜杠
  • 匹配以双引号结尾的字符串

"([^"]|(""))*?"


0

不知道这是否比m.buettner的更好或更差(猜测不会 - 他似乎很懂),但我想将其提交供评论。

"(([^"]+(""[^"]+"")*)*)"

1
我认为这个代码和 OP 的尝试有相同的问题。但是如果你删除第二个 "" 和最后一个 *,它应该和我的代码一样好(甚至更好,因为它实现了“展开循环”优化技术(@ridgerunner 如果看到这个答案,他会唱一首歌的 :D))。然而,+ 需要在双引号之间至少有一个非引号字符。你也应该把这些改成 *。(即 "([^"]*(""[^"]*)*)") - Martin Ender

0

尝试使用这个正则表达式 (?<=^")(.*?"{2}.*?"{2})(?="$),它可能比之前的两个更快,并且没有任何错误。


没有任何bug,是个相当大胆的说法,你不认为吗? ;) ... 这将愉快地匹配 "something"here"then""this""and"so"on""",但是不会匹配 "something""some""thing",以及 "some""thing""like""this"(后者因为它没有以三重引号结尾,而你的正则表达式要求这样) - Martin Ender

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接