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.