Regex non avide di Python


151

Come faccio a creare un regex di Python come "(.*)"tale, date le "a (b) c (d) e"corrispondenze di Python "b"invece di "b) c (d"?

So che posso usare "[^)]"invece di ".", ma sto cercando una soluzione più generale che mantenga il mio regex un po 'più pulito. C'è un modo per dire a Python "ehi, abbina questo al più presto"?

Risposte:


209

Cerchi l'onnipotente *?

Dai documenti, Greedy contro Non-Greedy

le qualificazioni non avidi *?, +?, ??, o {m,n}?[...] partita come piccolo testo possibile.


Secondo Internet Archive, tutto quel collegamento indicato era una copia dei documenti del modulo "re" di Python, quindi il collegamento di Trey funziona altrettanto bene.
spiffytech,

2
qual è il nome inglese comune per questo *??
Trevor Boyd Smith,

Personaggi jolly @Trevor Boyd Smith
Serge

3
Questo si chiama qualificatore "non avido"
brunetton

65
>>> x = "a (b) c (d) e"
>>> re.search(r"\(.*\)", x).group()
'(b) c (d)'
>>> re.search(r"\(.*?\)", x).group()
'(b)'

Secondo i documenti :

I qualificatori ' *', ' +' e ' ?' sono tutti golosi; corrispondono a più testo possibile. A volte questo comportamento non è desiderato; se RE <.*>corrisponde a " <H1>title</H1>", corrisponderà all'intera stringa e non solo a " <H1>". Aggiungendo ' ?' dopo la qualificazione, si esegue la partita in modo non avido o minimo; verranno abbinati il ​​minor numero di caratteri possibile. L'uso .*?nell'espressione precedente corrisponderà solo a " <H1>".


14

Non \\(.*?\\)funzionerebbe? Questa è la sintassi non avida.


5

Come hanno detto gli altri usando il? modificatore sul quantificatore * risolverà il tuo problema immediato, ma fai attenzione, stai cominciando a vagare in aree in cui le regex smettono di funzionare e hai invece bisogno di un parser. Ad esempio, la stringa "(foo (bar)) baz" ti causerà problemi.


5

L'uso di una partita non giocata è un buon inizio, ma suggerirei anche di riconsiderare qualsiasi uso di .*- che ne dici di questo?

groups = re.search(r"\([^)]*\)", x)

3

Vuoi che corrisponda a "(b)"? Fai come Zitrax e Paolo hanno suggerito. Vuoi che corrisponda a "b"? Fare

>>> x = "a (b) c (d) e"
>>> re.search(r"\((.*?)\)", x).group(1)
'b'

0

Per cominciare, non suggerisco di usare "*" nelle regex. Sì, lo so, è il delimitatore multi-carattere più usato, ma è comunque una cattiva idea. Questo perché, sebbene corrisponda a qualsiasi quantità di ripetizione per quel personaggio, "qualsiasi" include 0, che di solito è qualcosa per cui vuoi lanciare un errore di sintassi, che non accetta. Invece, suggerisco di usare il +segno, che corrisponde a qualsiasi ripetizione di lunghezza> 1. Inoltre, da quello che posso vedere, hai a che fare con espressioni tra parentesi a lunghezza fissa. Di conseguenza, è possibile probabilmente utilizzare la {x, y}sintassi per specificare in modo specifico la lunghezza desiderata.

Tuttavia, se hai davvero bisogno di ripetizioni non avide, ti suggerisco di consultare l'onnipotente ?. Questo, se posto dopo alla fine di qualsiasi identificatore di ripetizione regex, costringerà quella parte del regex a trovare la minima quantità di testo possibile.

Detto questo, starei molto attento a ?come, come il cacciavite sonico nel Dr. Who, ha la tendenza a fare, come dovrei dirlo, cose "leggermente" indesiderate se non calibrate con cura. Ad esempio, per utilizzare l'input di esempio, identifica ((1)(nota la mancanza di un secondo rparen) come una corrispondenza.

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.