一尘不染

使用正则表达式在C#中查找带转义引号的带引号的字符串

c#

我试图在一行上找到所有引用的文本。

例:

"Some Text"
"Some more Text"
"Even more text about \"this text\""

我需要得到:

  • "Some Text"
  • "Some more Text"
  • "Even more text about \"this text\""

\"[^\"\r]*\" 除了引号外,给了我所有的东西,因为引号已转义。

我已经阅读过有关\"[^\"\\]*(?:\\.[^\"\\]*)*\"工作的信息,但是在运行时出现错误:

parsing ""[^"\]*(?:\.[^"\]*)*"" - Unterminated [] set.

我该如何解决?


阅读 731

收藏
2020-05-19

共1个答案

一尘不染

您所拥有的是Friedl的“展开循环”技术的一个示例,但是您似乎对如何将其表示为字符串文字感到困惑。这是正则表达式编译器的外观:

"[^"\\]*(?:\\.[^"\\]*)*"

首字母"[^"\\]*与引号匹配,后跟零个或多个除引号或反斜杠之外的任何字符。仅此部分以及最终部分"将匹配一个简单的带引号的字符串,且没有嵌入的转义序列,例如"this"""

如果 确实
遇到反斜杠,则\\.消耗反斜杠及其后的所有内容,并且[^"\\]*(再次)消耗掉直到下一个反斜杠或引号的所有内容。该部分将根据需要重复多次,直到出现未转义的引号(或到达字符串的末尾并且匹配尝试失败)为止。

请注意,这将"foo\"-在中匹配\"foo\"-"bar"。这似乎暴露了正则表达式中的缺陷,但事实并非如此。这是无效的 输入
。目标是匹配带引号的字符串(可选地包含嵌入在其他文本中的反斜杠转义的引号)—为什么引号字符串 之外
的转义引号?如果您确实需要支持,那么您会遇到一个更加复杂的问题,需要一种截然不同的方法。

就像我说的,上面是正则表达式对正则表达式编译器的外观。但是,您是以字符串文字的形式编写它的,而这些字符串往往会特别对待某些字符,即反斜杠和引号。幸运的是,C#的逐字字符串免除了您必须两次转义反斜杠的麻烦。您只需要用另一个引号将每个引号引起来:

Regex r = new Regex(@"""[^""\\]*(?:\\.[^""\\]*)*""");

因此,规则是C#编译器使用双引号,而regex编译器使用双反斜杠-
既好又简单。这个特殊的正则表达式可能看起来有些尴尬,在两端都带有三个引号,但是请考虑以下选择:

Regex r = new Regex("\"[^\"\\\\]*(?:\\\\.[^\"\\\\]*)*\"");

在Java中,您 始终 必须以这种方式编写它们。:-(

2020-05-19