正则表达式和转义序列
我有一个文件,里面列出了要在数据库中查找的正则表达式。
其中一个模式是 (/|\)cmd\.com$
。但是当我用这个模式配合 re 模块时,会出现下面的错误。如果我把正则表达式改成 (/|\\\\)cmd\.com$
,就可以正常工作了。
所以,我的问题是,当我从文件中读取到一个变量,比如说 a,如何把它转换成一个正则表达式,并且需要四个反斜杠,这样它才能在 Python 的 re 模块中正常使用。
另外,当正则表达式被赋值给一个变量,比如下面的 "a",我们该如何处理这些转义序列呢?
任何帮助都非常感谢。
import re
a='(/|\)cmd\.com$'
re.compile(a)
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
File "/usr/lib/python2.6/re.py", line 190, in compile
return _compile(pattern, flags)
File "/usr/lib/python2.6/re.py", line 245, in _compile
raise error, v # invalid expression
sre_constants.error: unbalanced parenthesis
谢谢,
Santhosh
2 个回答
在你上面的例子中,你需要把正则表达式的模式写成Python的“原始”字符串,像这样:
re.compile(r'put the pattern here')
如果你把你的代码发出来,我可能能帮你解决关于从文件加载模式的问题。
首先要注意,你原来的正则表达式是无效的。正确的写法应该是 (/|\\)cmd\.com$
。如果这样的字符串是从数据库(或者其他非代码中的字符串来源)获取的,那么在正则引擎看到它之前不需要做额外的处理——斜杠是正确的。
详细解释如下:
反斜杠是特殊的,它可以让其他字符有不同的含义。
a = '(/|\)cmd\.com$'
在这个正则表达式中,)
是特殊的,表示一个分组表达式的结束;反斜杠用来转义它,使其被解释为字面上的 )
,而不是你想要的那样(这就是为什么你会收到关于括号不匹配的错误)。
你需要转义反斜杠,让它被解释为字面上的 \
;这可以通过再加一个反斜杠来实现:
a = '(/|\\)cmd\.com$'
不过即使这样也不行,因为在Python中有两个处理层次(因此需要两个层次的转义):首先,字符串字面量会被评估,反斜杠会被特别处理(在字符串处理中,比如 \.
是没有意义的,所以会被评估为 \.
——而 \\
会被评估为 \
)。然后,当正则引擎获取这个字符串时,它会特别处理那个对象中的任何字面反斜杠(在正则处理中,比如 \.
会让 .
被视为字面量,而不是“任何字符”)。所以你最终得到的是:
a = '(/|\\\\)cmd\\.com$' # Escaped version of (/|\\)cmd\.com$ which is what regex engine will see
因为这个问题非常常见,Python提供了一种写字符串的方法,使得反斜杠在字符串处理阶段 不会 被特别对待:“原始”字符串字面量:
a = r'(/|\\)cmd\.com$' # backslashes here will be interpreted as literal \ characters
正则引擎仍然会特别处理字符串中的反斜杠(原始字符串只是一种写字面量的方式;它仍然会生成一个普通的 str
对象)。