python" re"包装,奇怪的现象" raw"串

时间:2011-06-28 00:53:00

标签: python regex

我看到以下现象,似乎无法弄清楚,并且没有通过档案搜索找到任何内容:

如果我输入:

>>> if re.search(r'\n',r'this\nis\nit'):<br>
...     print 'found it!'<br>
... else:<br>
...     print "didn't find it"<br>
... 

我会得到:

didn't find it!

但是,如果我输入:

>>> if re.search(r'\\n',r'this\nis\nit'):<br>
...     print 'found it!'<br>
... else:<br>
...     print "didn't find it"<br>
... 

然后我会得到:

found it!

(第一个在r'\ n'上只有一个反斜杠,而第二个在r'\\ n'上连续有两个反斜杠......即使这个解释器正在删除其中一个。)<登记/>
我可以猜到发生了什么,但我不明白为什么会发生这种情况的官方机制:在第一种情况下,我需要逃避两件事:正则表达式和特殊字符串。 “Raw”让我逃避特殊字符串,但不是正则表达式。

但是第二个字符串中永远不会有正则表达式,因为它是匹配的字符串。所以只需要逃脱一次。

然而,对我来说似乎并不一致:我应该如何确保在第一种情况下字面真的?我可以输入rr''吗?或者我必须确保我逃避两次? 在类似的情况下,我如何确保变量是按字面意思(或者 NOT 字面意思)?例如,如果我有一个变量tmp ='this \ nis \ nmy \ nhome',我真的想找到斜杠和'n'的文字组合,而不是换行符怎么办?

谢谢!
麦克

3 个答案:

答案 0 :(得分:3)

re.search(r'\n', r'this\nis\nit')

正如你所说,“第二个字符串中永远不会有正则表达式。”所以我们需要以不同的方式查看这些字符串:第一个字符串是正则表达式,第二个字符串只是一个字符串。通常你的第二个字符串不是raw,所以任何反斜杠都是Python-escapes,而不是regex-escapes。

所以第一个字符串由文字“\”和“n”组成。这被正则表达式解析器解释为换行符(docs:“Python字符串文字支持的大多数标准转义符也被正则表达式解析器接受”)。所以你的正则表达式将搜索换行符。

你的第二个字符串由字符串“this”后跟一个文字“\”和一个“n”组成。所以这个字符串不包含实际的换行符。你的正则表达式不匹配。

关于你的第二个正则表达式:

re.search(r'\\n', r'this\nis\nit')

此版本匹配,因为您的正则表达式包含三个字符:文字“\”,另一个文字“\”和“n”。正则表达式解析器将两个斜杠解释为单个“\”字符,后跟“n”。所以你的正则表达式将搜索一个“\”后跟一个“n”,它在字符串中找到。但这并不是很有用,因为它与换行没有任何关系。

您最想要的是从第二个字符串中删除r,从而将其视为普通的Python字符串。

re.search(r'\n', 'this\nis\nit')

在这种情况下,你的正则表达式(如前所述)正在搜索换行符。并且,它找到它,因为第二个字符串包含单词“this”后跟换行符。

答案 1 :(得分:2)

转义字符串文字中的特殊序列是一回事,转义正则表达式特殊字符是另一回事。行字符串修饰符仅影响前者。

从技术上讲,re.search接受两个字符串,并使用re.compile将第一个字符串传递给正则表达式构建器。已编译的正则表达式对象用于搜索简单字符串中的模式。第二个字符串永远不会被编译,因此它不受正则表达式特殊字符规则的约束。

如果正则表达式构建器在处理字符串文字后收到\n,则会将此序列转换为换行符。如果你需要匹配序列,你也必须逃避它。

这背后的所有基本原理是正则表达式不是语言语法的一部分。它们在re模块内的标准库中处理,并使用该语言的公共构建块。

re.compile函数使用与最常用的正则表达式实现兼容的特殊字符和转义规则。但是,Python解释器不知道整个正则表达式概念,并且它不知道字符串文字是否将被编译为正则表达式对象。因此,Python无法提供任何类型的语法简化,例如您建议的那些。

答案 2 :(得分:1)

正则表达式对于文字反斜杠有自己的含义,如\d这样的字符类。如果你真的想要一个字面反斜杠字符,你实际上需要双重转义它。由于你正在将正则表达式与字符串进行比较,所以它实际上不应该是并行的。

原始字符串只是一种便利,拥有双原始字符串会有点过分。