Come usare una variabile all'interno di un'espressione regolare?


235

Vorrei usare un variableinterno a regex, come posso farlo in Python?

TEXTO = sys.argv[1]

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

9
Usi la concatenazione di stringhe
Chris Eberle il

Risposte:


52

Da python 3.6 in poi puoi anche usare Interpolazione letterale di stringhe , "f-stringhe". Nel tuo caso particolare la soluzione sarebbe:

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

MODIFICARE:

Dal momento che ci sono state alcune domande nel commento su come trattare con personaggi speciali, vorrei estendere la mia risposta:

stringhe non elaborate ('r'):

Uno dei concetti principali che devi comprendere quando hai a che fare con caratteri speciali nelle espressioni regolari è di distinguere tra letterali stringa e l'espressione regolare stessa. È molto ben spiegato qui :

In breve:

Diciamo invece di trovare un limite di parola \bdopo TEXTOaver voluto abbinare la stringa \boundary. Devi scrivere:

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

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

Questo funziona solo perché stiamo usando una stringa grezza (la regex è preceduta da 'r'), altrimenti dobbiamo scrivere "\\\\ limite" nella regex (quattro barre rovesciate). Inoltre, senza "\ r", \ b "non verrebbe più convertito in un limite di parole ma in uno spazio posteriore!

re.escape :

Fondamentalmente mette un backspace di fronte a qualsiasi personaggio speciale. Quindi, se ti aspetti un personaggio speciale in TEXTO, devi scrivere:

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

NOTA: per qualsiasi versione> = python 3.7: !, ", %, ', ,, /, :, ;, <, =, >, @, e `non sono sfuggiti. Solo i caratteri speciali con significato in una regex sono ancora sfuggiti. _non è sfuggito da Python 3.3. (vedi qui )

Parentesi graffe:

Se si desidera utilizzare quantificatori all'interno dell'espressione regolare utilizzando le stringhe f, è necessario utilizzare parentesi graffe doppie. Supponiamo che tu voglia abbinare TEXTO seguito da esattamente 2 cifre:

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

2
A partire dal 2020, questo è il modo più semplice e più pitonico di usare una variabile all'interno di un'espressione regolare
CONvid19

3
Questo è sicuramente un WOW .
Jason Goal

2
qualcuno può spiegare il significato di "rf" qui
Harsha Reddy,

1
@HarshaReddy: 'r': questa stringa è una stringa non elaborata: se non la usi, '\ b' verrà convertito nel carattere backspace ( docs.python.org/3/howto/regex.html#more- modello-potere ). 'f' dice a python che questa è una 'f-string', s. link sopra, e ti permette di scrivere la variabile tra parentesi graffe-
onda il

2
Come scrivere quantificatori in f-string: fr"foo{{1,5}}"(raddoppia le parentesi graffe)
PunchyRascal

281

Devi costruire il regex come una stringa:

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

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

Nota l'uso in re.escapemodo che se il tuo testo ha caratteri speciali, non saranno interpretati come tali.


4
Cosa succede se la tua variabile inizia per prima? r'' + foo + 'bar'?
deed02392,

@ deed02392 r''non è necessario se lo fai re.escape(foo), cosa che dovresti comunque. In realtà, penso che reinterpreti tutto ciò che viene dato come stringa unicode, indipendentemente dal fatto che tu abbia il prefisso ro meno.
OJFord,

.Format () funziona anche al posto di re.escape o è necessario re.escape ()?
Prassitele

@praxiteles hai trovato la risposta?
CONvocato

2
Non sono sicuro che se funziona, devo avere un gruppo di cui fa parte la variabile. Altre risposte di seguito sembrano più intuitive e non suddividono la regex in diverse espressioni.
Guiva

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

Ciò inserirà ciò che è in TEXTO nel regex come una stringa.



6

Trovo molto conveniente creare un modello di espressione regolare mettendo insieme più modelli più piccoli.

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)

Produzione:

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

4

Sono d'accordo con quanto sopra a meno che:

sys.argv[1] era qualcosa di simile Chicken\d{2}-\d{2}An\s*important\s*anchor

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

non vorresti usare re.escape, perché in quel caso vorresti che si comportasse come una regex

TEXTO = sys.argv[1]

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

2

Avevo bisogno di cercare nomi utente simili tra loro e ciò che Ned Batchelder ha detto è stato incredibilmente utile. Tuttavia, ho scoperto di avere un output più pulito quando ho usato re.compile per creare il mio termine di ricerca:

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

L'output può essere stampato usando quanto segue:

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

puoi provare un altro utilizzo usando formatsuger grammaticale:

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

0

Puoi usare anche la parola chiave format per questo. Il metodo Format sostituirà il segnaposto {} alla variabile che hai passato al metodo format come argomento.

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

0

più esempio

Ho configus.yml con i file di flussi

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

nel codice Python che uso

data_time_real_file=re.findall(r""+flows[flow]["pattern"][0]+"", latest_file)
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.