正则表达式和转义序列

-1 投票
2 回答
2983 浏览
提问于 2025-04-16 13:38

我有一个文件,里面列出了要在数据库中查找的正则表达式。

其中一个模式是 (/|\)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 个回答

1

在你上面的例子中,你需要把正则表达式的模式写成Python的“原始”字符串,像这样:

  re.compile(r'put the pattern here')

如果你把你的代码发出来,我可能能帮你解决关于从文件加载模式的问题。

3

首先要注意,你原来的正则表达式是无效的。正确的写法应该是 (/|\\)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 对象)。

撰写回答