13

我对python很陌生,所以我有一个字典,里面有一些键,还有一个字符串。如果在字典中找到的模式存在于字符串中,我必须替换字符串。字典和字符串都非常大。我正在使用正则表达式来查找模式。

一切正常,直到弹出这样的键 '-(' 或这个 '(-)' 在这种情况下,python 给出了不平衡括号的错误。

这是我编写的代码的外观:

somedict={'-(':'value1','(-)':'value2'}
somedata='this is some data containing -( and (-)'
for key in somedict.iterkeys():
    somedata=re.sub(key, 'newvalue', somedata)

这是我在控制台中遇到的错误

Traceback (most recent call last):
  File "<console>", line 2, in <module>
  File "C:\Python27\lib\re.py", line 151, in sub
    return _compile(pattern, flags).sub(repl, string, count)
  File "C:\Python27\lib\re.py", line 244, in _compile
    raise error, v # invalid expression
error: unbalanced parenthesis

我还使用正则表达式编译器尝试了很多方法并进行了很多搜索,但没有找到任何解决问题的方法。任何帮助表示赞赏。

4

2 回答 2

17

您需要使用以下命令转义密钥re.escape()

somedata = re.sub(re.escape(key), 'newvalue', somedata)

否则内容将被解释为正则表达式。

您在这里根本没有使用正则表达式,所以您不妨使用:

somedata = somedata.replace(key, 'newvalue')

如果您只想替换整个单词(因此在它们周围使用空格或标点符号,在输入字符串的开头或结尾),您需要某种边界锚点,此时使用正则表达式是有意义的。如果您只有字母数字单词(加上下划线),则\b可以:

somedata = re.sub(r'\b{}\b'.format(re.escape(key)), 'newvalue', somedata)

\b会在您要替换的字符串之前和之后放置,因此bazinfoo baz bar已更改,但foo bazbaz baris更改。

对于涉及非字母数字“单词”的输入,您需要将 whitespace-or-start 和 whitespace-or-end 锚点与前瞻和后视匹配:

somedata = re.sub(r'(?:^|(?<=\s)){}(?:$|(?=\s))'.format(re.escape(key)), 'newvalue', somedata)

在这里,该模式(?:^|(?<=\s))使用两个锚点,即字符串开头锚点和后视断言,以匹配字符串开头或紧靠左侧的空格的位置。同样(?:$|(?=\s)对另一端执行相同的操作,匹配字符串的结尾或后跟空格的位置。

于 2013-04-11T11:08:54.280 回答
2

不要re用于如此简单的事情 - 只需替换:

somedata = somedata.replace(key, 'newvalue')

也就是说,如果您正在从某些东西构建正则表达式,请使用re.escape转义特殊字符:

somedata=re.sub(re.escape(key), 'newvalue', somedata)
于 2013-04-11T11:09:55.237 回答