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

Jos*_*wry 40 c# regex quotes escaping

我试图在一行中找到所有引用的文本.

例:

"Some Text"
"Some more Text"
"Even more text about \"this text\""
Run Code Online (Sandbox Code Playgroud)

我需要得到:

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

\"[^\"\r]*\" 除了最后一个之外,它给了我所有的东西,因为有报道.

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

parsing ""[^"\]*(?:\.[^"\]*)*"" - Unterminated [] set.
Run Code Online (Sandbox Code Playgroud)

我该如何解决?

Ala*_*ore 79

你所拥有的是Friedl的"展开循环"技术的一个例子,但你似乎对如何将它表达为字符串文字有一些困惑.这是它应该如何看待正则表达式编译器:

"[^"\\]*(?:\\.[^"\\]*)*"
Run Code Online (Sandbox Code Playgroud)

初始"[^"\\]*匹配引号后跟零或更多除引号或反斜杠之外的任何字符.单独的那一部分,连同最后一部分",将匹配一个简单的引用字符串,没有嵌入的转义序列,如"this""".

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

请注意,这将匹配"foo\"-\"foo\"-"bar".这似乎暴露了正则表达式中的一个缺陷,但它没有; 这是输入无效.目标是匹配引用的字符串,可选地包含反斜杠转义的引号,嵌入在其他文本中 - 为什么引用字符串之外会有转义引号?如果你真的需要支持它,你就会遇到一个更复杂的问题,需要一种非常不同的方法.

正如我所说的,上面是正则表达式应该如何看待正则表达式编译器.但是你是以字符串文字的形式写的,而那些往往特别对待某些字符 - 即反斜杠和引号.幸运的是,C#的逐字字符串为您省去了双重逃避反斜杠的麻烦; 你只需要用另一个引号来逃避每个引号:

Regex r = new Regex(@"""[^""\\]*(?:\\.[^""\\]*)*""");
Run Code Online (Sandbox Code Playgroud)

所以规则是C#编译器的双引号和正则表达式编译器的双反斜杠 - 很简单.这个特殊的正则表达式可能看起来有点尴尬,两端都有三个引号,但请考虑替代方案:

Regex r = new Regex("\"[^\"\\\\]*(?:\\\\.[^\"\\\\]*)*\"");
Run Code Online (Sandbox Code Playgroud)

在Java中,您总是必须以这种方式编写它们.:-(


Ric*_*lde 12

用于捕获字符串(\用于字符转义)的正则表达式,用于.NET引擎:

(?>(?(STR)(?(ESC).(?<-ESC>)|\\(?<ESC>))|(?!))|(?(STR)"(?<-STR>)|"(?<STR>))|(?(STR).|(?!)))+   
Run Code Online (Sandbox Code Playgroud)

这里是一个"友好"的版本:

(?>                            | especify nonbacktracking
   (?(STR)                     | if (STRING MODE) then
         (?(ESC)               |     if (ESCAPE MODE) then
               .(?<-ESC>)      |          match any char and exits escape mode (pop ESC)
               |               |     else
               \\(?<ESC>)      |          match '\' and enters escape mode (push ESC)
         )                     |     endif
         |                     | else
         (?!)                  |     do nothing (NOP)
   )                           | endif
   |                           | -- OR
   (?(STR)                     | if (STRING MODE) then
         "(?<-STR>)            |     match '"' and exits string mode (pop STR)
         |                     | else
         "(?<STR>)             |     match '"' and enters string mode (push STR)
   )                           | endif
   |                           | -- OR
   (?(STR)                     | if (STRING MODE) then
         .                     |     matches any character
         |                     | else
         (?!)                  |     do nothing (NOP)  
   )                           | endif
)+                             | REPEATS FOR EVERY CHARACTER
Run Code Online (Sandbox Code Playgroud)

基于http://tomkaminski.com/conditional-constructs-net-regular-expressions示例.它依赖于报价平衡.我非常成功地使用它.与Singleline旗帜一起使用.

为了解决正则表达式,我推荐Rad Software正则表达式设计器,它有一个很好的"语言元素"选项卡,可以快速访问一些基本指令.它基于.NET的正则表达式引擎.