13

私は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 barは変更されません

英数字以外の「単語」を含む入力の場合、空白または開始および空白または終了アンカーを先読みおよび後読みと一致させる必要があります。

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

ここで、パターン(?:^|(?<=\s))は、文字列の開始アンカーと後読みアサーションの2 つのアンカーを使用して、文字列の開始またはすぐ左にスペースがある場所に一致させます。同様(?:$|(?=\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 に答える