2010-10-13 17 views
107

Ho una lista di stringhe. Alcuni di questi sono nella forma 123-...456. La parte variabile "..." può essere:Come abbinare, ma non catturare, parte di una regex?

  • la stringa "mela" seguita da un trattino, ad es. 123-apple-456
  • la stringa "banana" seguita da un trattino, ad es. 123-banana-456
  • una stringa vuota, ad es. 123-456 (nota c'è solo un trattino)

Qualsiasi parola diversa da "mela" o "banana" non è valido.

Per questi tre casi, vorrei abbinare rispettivamente "mela", "banana" e "". Si noti che non voglio mai catturare trattino, ma voglio sempre corrispondere a it. Se la stringa non è del formato 123-...456 come descritto sopra, non vi è alcuna corrispondenza.

Come si scrive un'espressione regolare per eseguire questa operazione? Supponiamo che io abbia un sapore che consente di guardare avanti, guardare indietro, cercare e gruppi non catturanti.


L'osservazione chiave qui è che quando si hanno o "mela" o "banana", è inoltre necessario avere il trattino finale, ma non si vuole abbinarlo. E quando stai abbinando la stringa vuota, tu non devi avere il trattino finale. Una regex che incapsula questa affermazione sarà quella giusta, penso.

+0

Dipende dal sapore regex. Quale linguaggio di programmazione e/o gusto regex stai usando? – BoltClock

+0

@BoltClock: aggiunto qualche chiarimento. Grazie per il feedback. –

+0

Vuoi abbinare tutto tranne i trattini? – BrunoLM

risposta

1

Prova questa:

/\d{3}-(?:(apple|banana)-)?\d{3}/ 
+1

Questo non è corretto poiché corrisponde, ad esempio, "123-coconut-456". –

+0

@david: com'è diverso dal tuo esempio "banana"? – SilentGhost

+0

@SilentGhost: I * only * desidera acquisire 'apple' o' banana' o "". Tutti gli altri valori non sono validi, come ho affermato. –

7

Prova:

123-(?:(apple|banana|)-|)456 

che abbinerà apple, banana, o una stringa vuota, e che lo seguono ci sarà un 0 o 1 trattini. Ho sbagliato a non avere bisogno di un gruppo di cattura. Silly me.

+0

Questo non è corretto poiché corrisponde, ad esempio, "123-coconut-456". –

+0

Pensavo volessi più generale ... risolto. – Thomas

+1

corrisponde a ''123--456'' – SilentGhost

105

L'unico modo per non catturare qualcosa sta usando look-around assertions:

(?<=123-)((apple|banana)(?=-456)|(?=456)) 

Perché anche con non-capturing groups (?:…) l'intera espressione regolare cattura loro contenuti abbinati. Ma questa espressione regolare corrisponde solo a apple o banana se preceduta da 123- e seguita da -456 oppure corrisponde alla stringa vuota se preceduta da 123- e seguita da 456.

+1

+1 - In questo caso, puoi ovviare a ciò usando il gruppo 1 anziché il gruppo 0, ma questa è una distinzione eccellente (e sottile!). –

+0

@ Blank: Dipende sicuramente da come vengono interpretati "match" e "capture". – Gumbo

+5

Non supportato in JavaScript, * yay *! sarebbe bello avere un metodo amichevole JS, ma non è affatto male, +0.5 (arrotondando per eccesso; D) – GiantCowFilms

9

Aggiornamento: Grazie a Germán Rodríguez Herrera!

In prova javascript: /123-(apple(?=-)|banana(?=-)|(?!-))-?456/

Ricordate che il risultato è nel gruppo 1

Regular expression visualization

Debuggex Demo

-2

Di gran lunga il più semplice (funziona per Python) è '123-(apple|banana)-?456'.

+0

Corrisponde a '123-apple456', quindi non è corretto. – Loren

1

ho modificato una delle risposte (da @ op1ekun):

123-(apple(?=-)|banana(?=-)|(?!-))-?456 

La ragione è che la risposta da @ op1ekun corrisponde anche "123-apple456", senza il trattino dopo la mela.

Problemi correlati