3

私の人生で複数のルックアラウンドを行う方法がわかりません。ハッシュに続く可変数の数値に一致させたいとしますが、前に何かがあったり、何か他のものが続いたりする場合は一致しません。たとえば、次の #123 または #12345 に一致させたいとします。後読みは問題ないように見えますが、先読みはそうではありません。私はアイデアがありません。

matches = ["#123", "This is #12345",
           # But not
           "bad #123", "No match #12345", "This is #123-ubuntu", 
           "This is #123 0x08"]

pat = '(?<!bad )(?<!No match )(#[0-9]+)(?! 0x0)(?!-ubuntu)'

for i in matches:
    print i, re.search(pat, i)
4

1 に答える 1

3

キャプチャーも必見です。あなたが得る最後の2つの文字列に賭けます:

#12

これが起こることです:

エンジンは 2 つの後読みをチェックしますが、それらは一致しないため、キャプチャ グループ#[0-9]+とmatch を続行し#123ます。これで、先読みがチェックされます。希望どおりに失敗します。しかし、今はバックトラックがあります!パターンには 1 つの変数があり、それは+. そのため、エンジンは最後に一致した文字 ( 3) を破棄し、再試行します。これで、先読みはもはや問題ではなくなり、一致が得られます。これを解決する最も簡単な方法は、最後の桁に移動することを確認する別の先読みを追加することです。

pat = r'(?<!bad )(?<!No match )(#[0-9]+)(?![0-9])(?! 0x0)(?!-ubuntu)'

生の文字列 (先頭のr) の使用に注意してください。このパターンでは問題ありませんが、文字をエスケープし始めると見苦しくなるため、一般的には良い習慣です。

編集:regexの代わりにパッケージを使用している、または使用する意思がある場合はre、バックトラッキングを抑制する所有量指定子が得られます。

pat = r'(?<!bad )(?<!No match )(#[0-9]++)(?! 0x0)(?!-ubuntu)'

どちらがより読みやすく、保守しやすいかはあなた次第です。ただし、後者の方がわずかに効率的です。(私にパッケージを教えてくれた nhahtdh に感謝しregexます。)

于 2013-04-25T00:58:26.000 に答える