Jak używać zmiennej w wyrażeniu regularnym?


235

Chciałbym skorzystać z variablewnętrza regex, jak mogę to zrobić Python?

TEXTO = sys.argv[1]

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

9
Używasz konkatenacji łańcuchów
Chris Eberle

Odpowiedzi:


52

Począwszy od Pythona 3.6 możesz także używać interpolacji ciągów literalnych , „f-string”. W twoim szczególnym przypadku rozwiązaniem byłoby:

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

EDYTOWAĆ:

Ponieważ w komentarzu pojawiło się kilka pytań dotyczących postępowania ze znakami specjalnymi, chciałbym rozszerzyć swoją odpowiedź:

nieprzetworzone ciągi („r”):

Jednym z głównych pojęć, które należy zrozumieć, posługując się znakami specjalnymi w wyrażeniach regularnych, jest rozróżnienie literałów łańcuchowych od samego wyrażenia regularnego. Jest to bardzo dobrze wyjaśnione tutaj :

W skrócie:

Powiedzmy, zamiast znaleźć granicę słowa \bpo TEXTOtym, jak chcesz dopasować ciąg \boundary. Musisz napisać:

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

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

Działa to tylko dlatego, że używamy nieprzetworzonego ciągu (wyrażenie regularne jest poprzedzone przez „r”), w przeciwnym razie musimy napisać „\\\\ granica” w wyrażeniu regularnym (cztery odwrotne ukośniki). Dodatkowo bez „\ r”, \ b ”nie zamieniłoby się już w granicę słów, ale w backspace!

re.escape :

Zasadniczo stawia backspace przed każdą postacią specjalną. Dlatego jeśli oczekujesz specjalnego znaku w TEXTO, musisz napisać:

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

UWAGA: Dla każdej wersji> = python 3.7: !, ", %, ', ,, /, :, ;, <, =, >, @, i `nie uciekł. Jedynie znaki specjalne mające znaczenie w wyrażeniu regularnym są nadal usuwane. _nie jest uciekany od Pythona 3.3. (s. tutaj )

Nawiasy klamrowe:

Jeśli chcesz używać kwantyfikatorów w wyrażeniu regularnym za pomocą f-stringów, musisz użyć podwójnych nawiasów klamrowych. Powiedzmy, że chcesz dopasować TEXTO, a następnie dokładnie 2 cyfry:

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

2
Począwszy od 2020 r. Jest to najprostszy i najbardziej pytoniczny sposób użycia zmiennej w wyrażeniu regularnym
CONvid19

3
To zdecydowanie WOW .
Jason Gol

2
czy ktoś może tutaj wyjaśnić znaczenie „rf”
Harsha Reddy

1
@HarshaReddy: 'r': Ten ciąg jest ciągiem surowym: jeśli go nie użyjesz, \ b b zostanie przekonwertowany na znak backspace ( docs.python.org/3/howto/regex.html#more- moc wzorcowa ). „f” mówi pythonowi, że jest to „f-string”, s. link powyżej i umożliwia zapisanie zmiennej w nawiasach klamrowych
powietrzu

2
Jak pisać kwantyfikatory w f-stringach: fr"foo{{1,5}}"(podwoić nawiasy klamrowe)
PunchyRascal

281

Musisz zbudować wyrażenie regularne jako ciąg:

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

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

Zwróć uwagę na użycie re.escape, aby jeśli twój tekst zawiera znaki specjalne, nie będą one interpretowane jako takie.


4
Co jeśli twoja zmienna jest pierwsza? r'' + foo + 'bar'?
deed02392,

@ deed02392 r''nie jest konieczne, jeśli to zrobisz re.escape(foo), co i tak powinieneś. Właściwie myślę, że reinterpretuje wszystko, co podano jako ciąg Unicode, niezależnie od tego, czy jest to prefiks, rczy nie.
OJFord,

Czy .format () działa również zamiast re.escape, czy też jest wymagana re.escape ()?
Praxiteles,

@praxiteles znalazłeś odpowiedź?
CONvid19,

2
Nie jestem pewien, czy to działa, muszę mieć grupę, której zmienna jest częścią. Inne odpowiedzi poniżej wyglądają na bardziej intuicyjne i nie dzielą wyrażenia regularnego na kilka wyrażeń.
gitarzysta

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

Spowoduje to wstawienie tego, co jest w TEXTO do wyrażenia regularnego jako łańcucha.



6

Uważam, że bardzo wygodne jest zbudowanie wzorca wyrażenia regularnego poprzez połączenie wielu mniejszych wzorców.

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)

Wynik:

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

4

Zgadzam się ze wszystkimi powyższymi, chyba że:

sys.argv[1] było coś w rodzaju Chicken\d{2}-\d{2}An\s*important\s*anchor

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

nie chciałbyś używać re.escape, ponieważ w takim przypadku chciałbyś, aby zachowywał się jak wyrażenie regularne

TEXTO = sys.argv[1]

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

2

Musiałem wyszukać nazwy użytkowników, które są do siebie podobne, a to, co powiedział Ned Batchelder, było niezwykle pomocne. Odkryłem jednak, że miałem czystsze dane wyjściowe, gdy użyłem re.compile, aby utworzyć termin ponownego wyszukiwania:

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

Dane wyjściowe można wydrukować za pomocą:

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

możesz spróbować innego użycia za pomocą formatgramatyki suger:

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

0

W tym przypadku można również użyć słowa kluczowego format.Format zastąpi symbol zastępczy {} zmienną przekazaną do metody format jako argument.

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

0

więcej przykładów

Mam configus.yml z plikami przepływów

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

w kodzie Pythona używam

data_time_real_file=re.findall(r""+flows[flow]["pattern"][0]+"", latest_file)
Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.