正規表現内で変数を使用するにはどうすればよいですか?


235

variable内部でを使用したいのですがregex、どうすればよいPythonですか?

TEXTO = sys.argv[1]

if re.search(r"\b(?=\w)TEXTO\b(?!\w)", subject, re.IGNORECASE):
    # Successful match
else:
    # Match attempt failed

9
文字列連結を使用します
Chris Eberle

回答:


52

Python 3.6以降では、リテラル文字列補間「f-strings」も使用できます。特定の場合の解決策は次のとおりです。

if re.search(rf"\b(?=\w){TEXTO}\b(?!\w)", subject, re.IGNORECASE):
    ...do something

編集:

特殊文字の扱い方についてコメントでいくつかの質問があったので、私の答えを拡張したいと思います:

生の文字列( 'r'):

正規表現で特殊文字を扱うときに理解する必要がある主な概念の1つは、文字列リテラルと正規表現自体を区別することです。ここで非常によく説明されています

要するに:

文字列に一致させたい\b後に単語の境界を見つける代わりに、としましょう。あなたは書く必要があります:TEXTO\boundary

TEXTO = "Var"
subject = r"Var\boundary"

if re.search(rf"\b(?=\w){TEXTO}\\boundary(?!\w)", subject, re.IGNORECASE):
    print("match")

これは、生の文字列を使用しているためにのみ機能します(正規表現の前に 'r'が付いています)。さらに、「\ r」がないと、\ b 'は単語の境界に変換されず、バックスペースに変換されます。

re.escape

基本的に、特殊文字の前にバックスペースを置きます。したがって、TEXTOで特殊文字が必要な場合は、次のように記述する必要があります。

if re.search(rf"\b(?=\w){re.escape(TEXTO)}\b(?!\w)", subject, re.IGNORECASE):
    print("match")

注:任意のバージョン> =のpython 3.7の場合:!"%',/:;<=>@、および`エスケープされません。正規表現で意味を持つ特殊文字のみがエスケープされます。_Pythonの3.3以降エスケープされていません。(S。ここ

中括弧:

fストリングを使用する正規表現内で数量詞を使用する場合は、二重の中括弧を使用する必要があります。TEXTOの後に正確に2桁が続くと一致するとします。

if re.search(rf"\b(?=\w){re.escape(TEXTO)}\d{{2}}\b(?!\w)", subject, re.IGNORECASE):
    print("match")

2
2020年の時点で、これは正規表現内で変数を使用する最も簡単で最もPython的な方法です
CONvid19

3
これは間違いなくあるWOW
ジェイソンゴール、

2
ここで「rf」の重要性を誰かが説明できますか
Harsha Reddy

1
@HarshaReddy: 'r':この文字列は未加工の文字列です。使用しない場合、 '\ b'はバックスペース文字に変換されます(docs.python.org/3/howto/regex.html#more-パターンパワー)。'f'は、これが 'f-string'であることをpythonに伝えます。上記のリンクをクリックして、変数を中括弧に書き込むことができます
空中

2
数量詞をf文字列で記述する方法:(fr"foo{{1,5}}"中かっこを2つ)
PunchyRascal

281

あなたは文字列として正規表現を構築する必要があります:

TEXTO = sys.argv[1]
my_regex = r"\b(?=\w)" + re.escape(TEXTO) + r"\b(?!\w)"

if re.search(my_regex, subject, re.IGNORECASE):
    etc.

の使用に注意してre.escapeください。テキストに特殊文字が含まれている場合、それらはそのように解釈されません。


4
変数が最初に行くとどうなりますか?r'' + foo + 'bar'
deed02392 2013

@ deed02392 r''を行う場合は不要re.escape(foo)です。実際には、reプレフィックスを付けるかどうかに関係なく、Unicode文字列として指定されたものはすべて解釈すると思いますr
OJFord 2014

.format()はre.escapeの代わりにも機能しますか、それともre.escape()が必要ですか?
Praxiteles、2016

@praxitelesあなたは答えを見つけましたか?
CONvid19

2
これが機能するかどうかはわかりませんが、変数が含まれるグループが必要です。以下の他の回答は、より直感的に見え、正規表現をいくつかの表現に分解しないでください。
偽装

48
if re.search(r"\b(?<=\w)%s\b(?!\w)" % TEXTO, subject, re.IGNORECASE):

これにより、TEXTOの内容が文字列として正規表現に挿入されます。



6

複数の小さいパターンをつなぎ合わせて正規表現パターンを作成するのは非常に便利です。

import re

string = "begin:id1:tag:middl:id2:tag:id3:end"
re_str1 = r'(?<=(\S{5})):'
re_str2 = r'(id\d+):(?=tag:)'
re_pattern = re.compile(re_str1 + re_str2)
match = re_pattern.findall(string)
print(match)

出力:

[('begin', 'id1'), ('middl', 'id2')]

4

私は上記のすべてに同意します:

sys.argv[1] のようなものでした Chicken\d{2}-\d{2}An\s*important\s*anchor

sys.argv[1] = "Chicken\d{2}-\d{2}An\s*important\s*anchor"

re.escapeその場合は正規表現のように動作させたいので、は使いたくないでしょう。

TEXTO = sys.argv[1]

if re.search(r"\b(?<=\w)" + TEXTO + "\b(?!\w)", subject, re.IGNORECASE):
    # Successful match
else:
    # Match attempt failed

2

私は互いに似ているユーザー名を検索する必要があり、Ned Batchelderの発言は非常に役に立ちました。しかし、re.compileを使用してre検索語句を作成したところ、より明確な出力が得られました。

pattern = re.compile(r"("+username+".*):(.*?):(.*?):(.*?):(.*)"
matches = re.findall(pattern, lines)

以下を使用して出力を印刷できます。

print(matches[1]) # prints one whole matching line (in this case, the first line)
print(matches[1][3]) # prints the fourth character group (established with the parentheses in the regex statement) of the first line.

1

format文法シュガーを使って別の使い方を試すことができます:

re_genre = r'{}'.format(your_variable)
regex_pattern = re.compile(re_genre)  

0

これにはformatキーワードも使用できます。Formatメソッドは、{}プレースホルダーを、引数としてformatメソッドに渡した変数に置き換えます。

if re.search(r"\b(?=\w)**{}**\b(?!\w)".**format(TEXTO)**, subject, re.IGNORECASE):
    # Successful match**strong text**
else:
    # Match attempt failed

0

もっと例

フローファイルを含むconfigus.ymlがあります

"pattern":
  - _(\d{14})_
"datetime_string":
  - "%m%d%Y%H%M%f"

私が使用するPythonコードで

data_time_real_file=re.findall(r""+flows[flow]["pattern"][0]+"", latest_file)
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.