2016-05-15 8 views
11

Ecco qualcosa che sto cercando di fare con le espressioni regolari, e non riesco a capire come. Ho un grande file e stringhe abc, 123 e xyz che compaiono più volte in tutto il file.Espressioni regolari: Garantire che b non sia tra a e c

Voglio un'espressione regolare per abbinare una stringa del grande file che inizia con abc, contiene 123 qualche parte nel mezzo, finisce con xyz, e non ci sono altre istanze di abc o xyz nella stringa, oltre l'avvio e la fine.

Ciò è possibile con le espressioni regolari?

+5

[Poiché le espressioni regolari non sono completamente standardizzate, tutte le domande con questo tag devono includere anche un tag che specifica il linguaggio o lo strumento di programmazione applicabile.] (Http://stackoverflow.com/tags/regex/info) Detto questo , c'è qualche ragione particolare per cui vuoi usare le espressioni regolari qui? È possibile, ma nella maggior parte degli ambienti è più complicato che non usare le espressioni regolari. – hvd

+0

Le interruzioni di riga dovrebbero essere considerate o no? Il grande file verrà letto riga per riga o come una grande stringa? –

+0

L'aroma Regex è python 2.7, i newline dovrebbero essere inclusi. –

risposta

17

Hai bisogno di un tempered greedy token:

abc(?:(?!abc|xyz|123).)*123(?:(?!abc|xyz).)*xyz 

Vedere regex demo

Per assicurarsi che corrisponda a linee, utilizzare il flag re.DOTALL durante la compilazione dell'espressione regolare.

Si noti che per ottenere prestazioni migliori con un modello così pesante, è consigliabile srotolarlo. Può essere fatto con classi di caratteri negati e lookaheads negativi.Dettagli

modello:

  • abc - Partita abc
  • (?:(?!abc|xyz|123).)* - qualsiasi carattere che non è il punto di partenza per un personaggio abc, xyz o 123 sequenze
  • 123 - una stringa letterale 123
  • (?:(?!abc|xyz).)* - qualsiasi carattere che non è il punto di partenza per un carattere abc o xyz sequenze
  • xyz - una stringa finale xyz

vedere lo schema seguente (se re.S utilizzato, . significherà AnyChar):

enter image description here

Vedere il Python demo:

0.123.516,41 mila
import re 
p = re.compile(r'abc(?:(?!abc|xyz|123).)*123(?:(?!abc|xyz).)*xyz', re.DOTALL) 
s = "abc 123 xyz\nabc abc 123 xyz\nabc text 123 xyz\nabc text xyz xyz" 
print(p.findall(s)) 
// => ['abc 123 xyz', 'abc 123 xyz', 'abc text 123 xyz'] 
+0

Puoi collegare il sito da dove hai generato quella macchina a stati? Conosco un sito con un'interfaccia utente simile ma non riesco a trovarlo. Ci scusiamo per il commento irrilevante. Lo eliminerò presto :) – rafid059

+2

Vedere https://jex.im/regulex –

+0

Perché il '| 123'? –

1

È possibile utilizzare il lookaround.

/^abc(?!.*abc).*123.*(?<!xyz.*)xyz$/g 

(non ho provato).

2

Il comment da hvd è molto opportuno, e questo solo fornisce un esempio. In SQL, per esempio, penso che sarebbe più chiaro fare:

where val like 'abc%123%xyz' and 
     val not like 'abc%abc%' and 
     val not like '%xyz%xyz' 

immagino qualcosa di molto simile è semplice da fare in altri ambienti.

1

Utilizzando PCRE una soluzione sarebbe:

Questa utilizzando m bandiera. Se si desidera controllare solo all'inizio e alla fine di una linea di aggiungere ^ e $ all'inizio e alla fine rispettivamente

abc(?!.*(abc|xyz).*123).*123(?!.*(abc|xyz).*xyz).*xyz 

Regular expression visualization

Debuggex Demo

Problemi correlati