Wie verwende ich eine Variable in einem regulären Ausdruck?

234

Ich möchte ein variableInside A verwenden regex. Wie kann ich das tun Python?

TEXTO = sys.argv[1]

if re.search(r"\b(?=\w)TEXTO\b(?!\w)", subject, re.IGNORECASE):
    # Successful match
else:
    # Match attempt failed
CONvid19
quelle
9
Sie verwenden String-Verkettung
Chris Eberle

Antworten:

51

Ab Python 3.6 können Sie auch die Literal String Interpolation "f-strings" verwenden. In Ihrem speziellen Fall wäre die Lösung:

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

BEARBEITEN:

Da der Kommentar einige Fragen zum Umgang mit Sonderzeichen enthält, möchte ich meine Antwort erweitern:

rohe Saiten ('r'):

Eines der Hauptkonzepte, die Sie beim Umgang mit Sonderzeichen in regulären Ausdrücken verstehen müssen, ist die Unterscheidung zwischen Zeichenfolgenliteralen und dem regulären Ausdruck selbst. Es ist sehr gut erklärt hier :

Zusamenfassend:

Nehmen wir an, anstatt eine Wortgrenze zu finden, \bnachdem TEXTOSie mit der Zeichenfolge übereinstimmen möchten \boundary. Das musst du schreiben:

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

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

Dies funktioniert nur, weil wir eine Rohzeichenfolge verwenden (vor dem regulären Ausdruck steht 'r'), andernfalls müssen wir "\\\\ Grenze" in den regulären Ausdruck schreiben (vier Backslashes). Außerdem würde \ b 'ohne' \ r 'nicht mehr in eine Wortgrenze konvertiert, sondern in eine Rücktaste!

re.escape :

Grundsätzlich wird vor jedem Sonderzeichen eine Rücktaste eingefügt. Wenn Sie also in TEXTO ein Sonderzeichen erwarten, müssen Sie Folgendes schreiben:

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

HINWEIS: Für jede Version> = Python 3.7: !, ", %, ', ,, /, :, ;, <, =, >, @, und `sind nicht entgangen. Es werden nur noch Sonderzeichen mit Bedeutung in einem regulären Ausdruck maskiert. _wird seit Python 3.3 nicht mehr maskiert. (s. hier )

Geschweifte Klammern:

Wenn Sie Quantifizierer innerhalb des regulären Ausdrucks mit f-Strings verwenden möchten, müssen Sie doppelte geschweifte Klammern verwenden. Angenommen, Sie möchten mit TEXTO übereinstimmen, gefolgt von genau zwei Ziffern:

if re.search(rf"\b(?=\w){re.escape(TEXTO)}\d{{2}}\b(?!\w)", subject, re.IGNORECASE):
    print("match")
in der Luft
quelle
2
Ab 2020 ist dies die einfachste und pythonischste Methode, eine Variable in einem regulären Ausdruck zu verwenden
CONvid19
3
Dies ist definitiv ein WOW .
Jason Goal
2
kann jemand hier die Bedeutung von "rf" erklären
Harsha Reddy
1
@HarshaReddy: 'r': Diese Zeichenfolge ist eine Rohzeichenfolge: Wenn Sie sie nicht verwenden, wird '\ b' in das Backspace-Zeichen konvertiert ( docs.python.org/3/howto/regex.html#more- Musterkraft ). 'f' sagt Python, dass dies ein 'f-String' ist, s. Link oben, und ermöglicht es Ihnen, die Variable in die geschweiften Klammern zu schreiben
Luft
1
Entgeht dies Sonderzeichen in der ersetzten Zeichenfolge? Nur von einem kleinen Test scheint es nicht. re.escape()wird noch benötigt
Tugzrida
281

Sie müssen den regulären Ausdruck als Zeichenfolge erstellen:

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

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

Beachten Sie die Verwendung von, re.escapedamit Ihr Text Sonderzeichen nicht als solche interpretiert.

Ned Batchelder
quelle
4
Was ist, wenn Ihre Variable zuerst geht? r'' + foo + 'bar'?
deed02392
@ deed02392 r''nicht notwendig, wenn du das tust re.escape(foo), was du sowieso tun solltest. Eigentlich denke ich, reinterpretiert alles, was es gibt, als Unicode-Zeichenfolge, unabhängig davon, ob Sie ein Präfix verwenden roder nicht.
OJFord
Funktioniert .format () auch anstelle von re.escape oder ist re.escape () erforderlich?
Praxiteles
@praxiteles hast du die Antwort gefunden?
CONvid19
2
Ich bin mir nicht sicher, ob dies funktioniert. Ich brauche eine Gruppe, zu der die Variable gehört. Andere Antworten unten sehen dafür intuitiver aus und teilen den regulären Ausdruck nicht in mehrere Ausdrücke auf.
Guival
48
if re.search(r"\b(?<=\w)%s\b(?!\w)" % TEXTO, subject, re.IGNORECASE):

Dadurch wird das, was in TEXTO enthalten ist, als Zeichenfolge in den regulären Ausdruck eingefügt.

Bo Buchanan
quelle
37
rx = r'\b(?<=\w){0}\b(?!\w)'.format(TEXTO)
Cat Plus Plus
quelle
6

Ich finde es sehr praktisch, ein Muster für reguläre Ausdrücke zu erstellen, indem mehrere kleinere Muster aneinandergereiht werden.

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)

Ausgabe:

[('begin', 'id1'), ('middl', 'id2')]
Deepak Nagarajan
quelle
4

Ich stimme allen oben genannten Punkten zu, es sei denn:

sys.argv[1] war so etwas wie Chicken\d{2}-\d{2}An\s*important\s*anchor

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

Sie möchten nicht verwenden re.escape, da Sie in diesem Fall möchten, dass es sich wie ein regulärer Ausdruck verhält

TEXTO = sys.argv[1]

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

Ich musste nach Benutzernamen suchen, die einander ähnlich sind, und was Ned Batchelder sagte, war unglaublich hilfreich. Ich stellte jedoch fest, dass ich eine sauberere Ausgabe hatte, als ich re.compile verwendete, um meinen Forschungsbegriff zu erstellen:

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

Die Ausgabe kann wie folgt gedruckt werden:

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.
jdelaporte
quelle
1

Sie können eine andere Verwendung mit formatGrammer Suger versuchen :

re_genre = r'{}'.format(your_variable)
regex_pattern = re.compile(re_genre)  
Kevin Chou
quelle
0

Sie können auch das Format-Schlüsselwort verwenden. Die Format-Methode ersetzt den Platzhalter {} durch die Variable, die Sie als Argument an die Format-Methode übergeben haben.

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

mehr Beispiel

Ich habe configus.yml mit Flows-Dateien

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

im Python-Code verwende ich

data_time_real_file=re.findall(r""+flows[flow]["pattern"][0]+"", latest_file)
Nikolay Baranenko
quelle