为什么这两个python正则表达式产生不同的结果?

时间:2016-08-22 22:38:34

标签: python regex

>>> re.match(r'"([^"]|(\\\"))*"', r'"I do not know what \"A\" is"').group(0)
'"I do not know what \\"'
>>> re.match(r'"((\\\")|[^"])*"', r'"I do not know what \"A\" is"').group(0)
'"I do not know what \\"A\\" is"'

这两个正则表达式用于查找带引号的字符串,带有转义引号序列。除非我遗漏了某些东西,否则差异就是括号中分离的顺序。

为什么他们都不接受整个字符串?

3 个答案:

答案 0 :(得分:2)

你说的是真的,顺序是不同的。还有别的不一样 第一个"([^"]|(\\\"))*"将匹配逃生,使其成为 匹配"asdf\" sde"而另一个则没有。

此外,如果你必须处理转义引用,你也必须处理转义。所以,两者都不是有效的。

以下是两种标准方法。
两者都处理逃脱。
您也可以将其扩展为单引号 如果您想跨越换行符,请使用Dot-All修饰符(?s)

方法1. - 交替

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

 " 
 (?:
      \\ .                 # Escape anything
   |                     # or,
      [^"\\]+              # Not escape not quote
 )*
 "

方法2. - 展开循环

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

 " 
 [^"\\]*          # Optional not escape not quote
 (?:
      \\ .             # Escape anything
      [^"\\]*          # Optional not escape not quote
 )*
 "

两者都这样做。方法2比方法1快三到五倍。

答案 1 :(得分:1)

交替小组的顺序很重要。

在第一个正则表达式中,首先为每个字符尝试[^"]替代。它匹配每个单个字符,直至(包括)第一个\。在下一个字符(")上,此替代字符([^"])失败,另一个字符(\\\")尝试。后者也失败,因为"A\\\"不匹配。这会使量词*停止进一步匹配。

在第二个正则表达式中,\\\"替代(括号是多余的)首先尝试每个字符并失败,因此第二个替代([^"])匹配。但是在第一个\处,第一个替代匹配,因此查找指针移过\"A并继续查找。

作为一般经验法则,首先将最窄的表达式放在交替中。

答案 2 :(得分:0)

正则表达式r'(A|B)'将首先尝试匹配A,并且只有在失败后才会尝试匹配B(docs

因此正则表达式([^"]|(\\\")将首先尝试匹配非引用,如果失败,它将尝试匹配转义的引号。

因此,当正则表达式达到\"A\"时,第一部分与\匹配(它不是引号。但是这两个部分都不匹配",所以匹配结束于那里。反斜杠被[^"]吞噬,因此表达式的后半部分从未使用过。

转到((\\“)| [^”]),当它到达\"A\"时会首先尝试匹配\"(它有效)然后它将尝试匹配{{1 (它匹配A,因此匹配继续。