Regex con parte facoltativa non crea backreference
-
26-09-2019 - |
Domanda
Voglio corrispondere un tag facoltativa alla fine di una riga di testo.
testo di input Esempio:
The quick brown fox jumps over the lazy dog {tag}
Voglio corrispondere alla parte in parentesi graffe e creare un back-riferimento ad esso.
I miei sguardi regex come questo:
^.*(\{\w+\})?
(un po 'semplificato, sto anche corrispondenti parti prima del tag):
Si abbina l'ok linee (con e senza il cartellino), ma non crea un back-riferimento al tag.
Se rimuovo il '?' carattere, quindi regex è:
^.*(\{\w+\})
Si crea un back-riferimento al tag, ma poi non corrisponde linee senza il cartellino.
ho capito da http://www.regular-expressions.info/refadv.html che l'operatore opzionale non inciderebbe sulla backreference:
Rotonda parentesi gruppo l'espressione regolare tra di loro. Catturano il testo di pari passo con l'espressione regolare al loro interno che può essere riutilizzato in un backreference, e permettono di applicare operatori regex a tutta la regex raggruppati.
, ma deve aver frainteso qualcosa.
Come faccio opzionale tag parte e creare un back-riferimento quando esiste?
Soluzione
Non è un problema backreference, il problema è che l'espressione regolare è stato soddisfatto da solo leggendo nel testo che .*
abbinato. Non si sentiva in dovere di continuare a leggere per leggere il tag di fine opzionale. La soluzione più semplice se stai veramente lettura alla fine della linea è quello di aggiungere un $
(simbolo di dollaro) per forzare l'espressione regolare per abbinare l'intera linea.
modifica
A proposito, non ho preso il tuo reg-ex letteralmente in quanto lei ha detto che soddisfa le altre cose, ma solo per essere chiari .*
consumerà tutta la linea. Avresti bisogno di qualcosa come [^{]*
per evitare che il tag di ottenere ingerito. Sto indovinando che non è un problema per voi.
Altri suggerimenti
In aggiunta a ciò che gli altri hanno spiegato, si potrebbe desiderare di fare il .*
"pigro":
^.*?(\{\w+\})?
Come David Gladfelter detto, il vero problema è che quando si rendono facoltativa, che non corrisponde ; tuttavia, il suo fix proposto non funziona . Modifica 1: Avrai bisogno di utilizzare ciò che ha messo nella sua modifica (che ha ottenuto scritto come stavo scrivendo questo). Il problema è che i quantificatori (*
, +
, ?
, {n,m}
) sono avido : hanno sempre corrispondano quanto più possibile. Così, quando si scrive ^.*(\{\w+\})?
, il .*
corrisponde sempre tutta la linea, perché un vuoto soddisfa partita del gruppo opzionale. Si noti inoltre che, sebbene ?
è avido, il primo greediness (di .*
) ha la precedenza. Se ti è permesso solo per avere parentesi graffe intorno a quel gruppo opzionale, quindi è possibile risolvere il problema dicendo esplicitamente: ^[^\{]*(\{\w+\})?
. In questo modo, il primo pezzo corrisponderà tutto fino alla prima parentesi graffa, e poi (dal ?
è avido) se si può abbinare la parola riccio-parentesi.
Spesso, un altro modo per risolvere questo è quello di rendere i quantificatori pigro (o non-avido, minimal, etc.) aggiungendo un ?
: *?
, +?
, ??
e {n,m}?
. Tuttavia, questo non vi aiuterà qui: invece, se si fa ^.*?(\{\w+\})?
, il .*?
pigro cercherà di abbinare zero caratteri, avere successo, e quindi il gruppo opzionale non corrisponderà. Eppure, anche se non funziona qui, è uno strumento utile nella vostra cassetta degli attrezzi. Modifica 1:. Si noti inoltre che questi non sono disponibili in tutti i motori regex, anche se sono disponibili in C #
Grazie ragazzi. Ho usato una combinazione di risposte, il modificatore non-avidi e la partita di fine linea, che sembra fare il trucco, in modo da regex è ora:
^.*?(\{\w+\})?$
Non voleva usare [^ {] * per la prima parte della partita, come non-tag parentesi graffe possono apparire qui, ma i tag sarà sempre alla fine della linea.
Grazie per le risposte, erano tutti disponibili.
se siete interessati solo nel tag, e non si preoccupa il resto della stringa, allora si sarebbe rendere la vita molto più facile semplicemente corrispondenti al tag con questo regex ( vedere su rubular.com ):
\{(\w+)\}$
Questo è, si sta cercando di abbinare qualche {word}
alla fine della stringa. Se non è lì, poi troppo male, non c'è alcuna corrispondenza. Non v'è alcuna necessità di un modificatore ?
o un .*
riluttante e tutta quella roba.
In C #, si potrebbe anche voler utilizzare RegexOptions.RightToLeft
, dal momento che si sta cercando di abbinare un suffisso comunque, quindi forse qualcosa di simile:
string[] lines = {
"The quick brown fox jumps over the lazy dog",
"The quick brown fox jumps over the lazy dog {tag}",
"The quick brown fox jumps over the {lazy} dog",
"The quick brown fox jumps over the {lazy} {dog}",
};
Regex r = new Regex(@"\{(\w+)\}$", RegexOptions.RightToLeft);
foreach (string line in lines) {
Console.WriteLine("[" + r.Match(line).Groups[1] + "]");
}
Questo stampa ( come visto in ideone.com ):
[]
[tag]
[]
[dog]