Nozioni di base sull'espressione regolare in C ++

Nozioni di base sull'espressione regolare in C ++
Considera la seguente frase tra citazioni: "Ecco il mio uomo."

Questa stringa potrebbe essere all'interno del computer e l'utente potrebbe voler sapere se ha la parola "uomo". Se ha la parola uomo, potrebbe quindi voler cambiare la parola "uomo" in "donna"; in modo che la stringa debba leggere:

"Ecco la mia donna."

Ci sono molti altri desideri come questi dall'utente del computer; Alcuni sono complessi. Espressione regolare, abbreviata, regex, è oggetto di gestire questi problemi dal computer. C ++ viene fornito con una libreria chiamata Regex. Quindi, un programma C ++ per gestire Regex dovrebbe iniziare:

#includere
#includere
Utilizzo dello spazio dei nomi std;

Questo articolo spiega le basi delle espressioni regolari in C++.

Contenuto dell'articolo

  • Fondamenti di espressione regolari
  • Modello
  • Classi di personaggi
  • Spazi bianchi abbinati
  • Il periodo (.) nel modello
  • Ripetizioni corrispondenti
  • Alternamento corrispondente
  • Inizio o fine corrispondente
  • Raggruppamento
  • ICase e Multiline Regex_Constants
  • Abbinare l'intero bersaglio
  • L'oggetto Match_Results
  • Posizione della corrispondenza
  • Cerca e sostituisci
  • Conclusione

Fondamenti di espressione regolari

Regex

Una stringa come "Ecco il mio uomo."Sopra è la sequenza target o la stringa target o semplicemente, target. "Uomo", che è stato cercato, è l'espressione regolare, o semplicemente, Regex.

Abbinamento

Si dice che si verifichi la corrispondenza quando si trova la parola o la frase che viene cercato. Dopo la corrispondenza, può avvenire una sostituzione. Ad esempio, dopo che "Man" si trova sopra, può essere sostituito da "donna".

Semplice abbinamento

Il seguente programma mostra come viene abbinata la parola "uomo".

#includere
#includere
Utilizzo dello spazio dei nomi std;
int main ()

regex reg ("uomo");
if (regex_search ("Ecco il mio uomo.", reg)
cout << "matched" << endl;
altro
cout << "not matched" << endl;
restituzione 0;

La funzione regex_search () restituisce true se c'è una corrispondenza e restituisce falso se non si verifica alcuna corrispondenza. Qui, la funzione prende due argomenti: la prima è la stringa di destinazione e la seconda è l'oggetto regex. Il Regex stesso è "uomo", in doppia citazione. La prima istruzione nella funzione principale () forma l'oggetto regex. Regex è un tipo e Reg è l'oggetto regex. L'output del programma di cui sopra è "abbinato", poiché "l'uomo" è visto nella stringa target. Se "uomo" non fosse stato visto nel bersaglio, regex_search () sarebbe stato restituito falso e l'output sarebbe stato "non abbinato".

L'output del seguente codice è "non abbinato":

regex reg ("uomo");
if (regex_search ("Ecco il mio creazione.", reg)
cout << "matched" << endl;
altro
cout << "not matched" << endl;

Non abbinato perché "l'uomo" di regex non è stato trovato nell'intera stringa di destinazione ", ecco il mio fare."

Modello

L'espressione regolare, "uomo" sopra, è molto semplice. I regex di solito non sono così semplici. Le espressioni regolari hanno metacharacter. I metacharacter sono personaggi con significati speciali. Un metacharacter è un personaggio sui personaggi. C ++ regex metacharacters sono:

^ $ \ . * + ? () [] |

Un regex, con o senza metacharacter, è uno schema.

Classi di personaggi

Parentesi quadre

Uno schema può avere caratteri tra parentesi quadrate. Con questo, una posizione particolare nella stringa di destinazione corrisponderebbe a uno qualsiasi dei personaggi delle parentesi quadrate. Considera i seguenti obiettivi:

"Il gatto è nella stanza."
"Il pipistrello è nella stanza."
"Il topo è nella stanza."

Il regex, [CBR] AT avrebbe abbinato il gatto nel primo bersaglio. Corrisponderebbe alla mazza nel secondo bersaglio. Corrisponderebbe al topo nel terzo bersaglio. Questo perché "Cat" o "Bat" o "Rat" inizia con "C" o "B" o "R". Il seguente segmento di codice illustra questo:

regex reg ("[cbr] at");
if (regex_search ("Il gatto è nella stanza.", reg)
cout << "matched" << endl;
if (regex_search ("Il pipistrello è nella stanza.", reg)
cout << "matched" << endl;
if (regex_search ("Il ratto è nella stanza.", reg)
cout << "matched" << endl;

L'output è:

abbinato
abbinato
abbinato

Gamma di personaggi

La classe, [CBR] nel modello [CBR], corrisponderebbe a diversi possibili caratteri nel bersaglio. Corrisponderebbe a "c" o "b" o "r" nel bersaglio. Se il bersaglio non ha nessuno di "c" o "b" o "r", seguito da "at", non ci sarebbe alcuna corrispondenza.

Alcune possibilità come 'C' o 'B' o 'r' esistono in un intervallo. La gamma di cifre, da 0 a 9 ha 10 possibilità e il modello è [0-9]. La gamma di alfabeti minuscoli, da A a Z, ha 26 possibilità e il modello per questo è [A-Z]. La gamma di alfabeti maiuscole, da A a Z, ha 26 possibilità e il modello per questo è [A-Z]. - non è ufficialmente un metacharacter, ma all'interno delle parentesi quadrate indicherebbe un intervallo. Quindi, quanto segue produce una partita:

if (regex_search ("id6id", regex ("[0-9]")))
cout << "matched" << endl;

Nota come il regex è stato costruito come secondo argomento. La partita si verifica tra la cifra, 6 nell'intervallo, da 0 a 9 e il 6 nel bersaglio, "Id6id". Il codice sopra è equivalente a:

if (regex_search ("id6id", regex ("[0123456789]")))
cout << "matched" << endl;

Il seguente codice produce una corrispondenza:

char str [] = "id6ie";
if (regex_search (str, regex ("[a-z]")))
cout << "matched" << endl;

Si noti che il primo argomento qui è una variabile stringa e non la stringa letterale. La partita è tra "I" in [A-Z] e "I" in "Id6ie".

Non dimenticare che una gamma è una classe. Può esserci un testo a destra della gamma o a sinistra dell'intervallo nel modello. Il seguente codice produce una corrispondenza:

if (regex_search ("id2idpost-95222 -__ ddelink__294_3116034780"> è un ID ", regex (" id [0-9] id "))))
cout << "matched" << endl;

La partita è tra "id [0-9] id" e "id2id". Il resto della stringa target, "è un ID", non è abbinato in questa situazione.

Come usato nel soggetto di espressione regolare (regexes), la classe Word in realtà significa un set. Cioè, uno dei personaggi nel set è corrispondere.

Nota: il trattino - è un metacharacter solo tra parentesi quadrate, indicando un intervallo. Non è un metacharacter nel regex, al di fuori delle staffe quadrate.

Negazione

Una classe che include una gamma può essere annullata. Cioè, non dei personaggi nel set (classe) dovrebbe corrispondere. Questo è indicato con il ^ metacharacter all'inizio del modello di classe, subito dopo la fascia quadrata di apertura. Quindi, [^0-9] significa abbinare il carattere nella posizione appropriata nel bersaglio, che non è un carattere nell'intervallo, da 0 a 9 inclusivi. Quindi il seguente codice non produrrà una corrispondenza:

if (regex_search ("0123456789101112", regex ("[^0-9]")))
cout << "matched" << endl;
altro
cout << "not matched" << endl;

Una cifra all'interno dell'intervallo da 0 a 9 potrebbe essere trovata in una qualsiasi delle posizioni della stringa di destinazione, "0123456789101112"; Quindi non c'è corrispondenza - negazione.

Il seguente codice produce una corrispondenza:

if (regex_search ("abcdefghij", regex ("[^0-9]")))
cout << "matched" << endl;

Non è stata trovata nessuna cifra nel bersaglio, "abcdefghij"; Quindi c'è una partita.

[A-Z] è un intervallo al di fuori [^A-Z]. E così [^a-z] è la negazione di [a-z].

[A-Z] è un intervallo al di fuori [^A-Z]. E così [^a-z] è la negazione di [a-z].

Esistono altre negazioni.

Spazi bianchi abbinati

"o \ t o \ r o \ n o \ f è un carattere di spazio bianco. Nel seguente codice, il regex, "\ n" corrisponde '\ n' nel bersaglio:

if (regex_search ("della linea uno.\ r \ nof riga due.", regex (" \ n ")))
cout << "matched" << endl;

Abbinare qualsiasi personaggio di spazi bianchi

Il modello o la classe per abbinare qualsiasi carattere di spazio bianco è, [\ t \ r \ n \ f]. Nel seguente codice, "è abbinato:

if (regex_search ("uno due", regex ("[\ t \ r \ n \ f]")))
cout << "matched" << endl;

Corrispondere a qualsiasi personaggio non Whitespace

Il modello o la classe per abbinare qualsiasi carattere spaziale non bianco è, [^ \ t \ r \ n \ f]. Il seguente codice produce una corrispondenza perché non c'è spazio bianco nel bersaglio:

if (regex_search ("1234abcd", regex ("[^ \ t \ r \ n \ f]")))
cout << "matched" << endl;

Il periodo (.) nel modello

Il periodo (.) nel modello corrisponde a qualsiasi carattere incluso se stesso, tranne \ n, nel bersaglio. Una partita è prodotta nel seguente codice:

if (regex_search ("1234abcd", regex (".")))
cout << "matched" << endl;

Nessun risultato corrispondente nel seguente codice perché l'obiettivo è "\ n".

if (regex_search ("\ n", regex (".")))
cout << "matched" << endl;
altro
cout << "not matched" << endl;

Nota: all'interno di una classe di caratteri con parentesi quadrate, il periodo non ha un significato speciale.

Ripetizioni corrispondenti

Un carattere o un gruppo di caratteri può verificarsi più di una volta all'interno della stringa di destinazione. Un modello può abbinare questa ripetizione. I metacharacter, ?, *, +e sono usati per abbinare la ripetizione nel bersaglio. Se x è un carattere di interesse per la stringa target, i metacharacter hanno i seguenti significati:

x*: significa corrispondere 'x' 0 o più volte, i.e., qualsiasi numero di volte
x+: significa corrispondere 'x' 1 o più volte, i.e., almeno una volta
X? : significa abbinare 'x' 0 o 1 volta
x n,: significa corrispondenza 'x' almeno n o più volte. Nota la virgola.
x n: match 'x' esattamente n volte
x n, m: match 'x' almeno n volte, ma non più di m volte.

Questi metacharacter sono chiamati quantificatori.

Illustrazioni

*

* Corrisponde al carattere precedente o al gruppo precedente, zero o più volte. "O*" corrisponde a 'O' in “Dog” della stringa bersaglio. Si abbina anche a "OO" in "Book" e "Looking". The Regex, "O*" corrisponde a "Boooo" in "The Animal Booooed.". Nota: "O*" corrisponde a "Dig", dove 'O' si verifica zero (o più) tempo.

+

Il + corrisponde al carattere precedente o al gruppo precedente, 1 o più volte. Contrastalo con zero o più volte per *. Quindi il regex, "e+" corrisponde a "e" in "eat", dove si verifica una volta. "E+" corrisponde anche a "EE" in "Sheep", dove "E" si verifica più di una volta. Nota: "E+" non corrisponderà a "Dig" perché in "Dig", "E" non si verifica almeno una volta.

?

IL ? corrisponde al carattere precedente o al gruppo precedente, 0 o 1 volta (e non di più). Quindi, “E?"Corrisponde a" dig "perché 'e' si verifica in“ dig ”, zero tempo. “E?"Corrisponde a" set "perché 'e' si verifica in“ set ”, una volta. Nota: “E?"Abbina ancora" Sheep "; Anche se ci sono due e "in" pecora ". C'è una sfumatura qui - vedi più tardi.

N,

Questo corrisponde almeno a ripetizioni consecutive di un carattere precedente o di un gruppo precedente. Quindi il regex, "e 2," corrisponde alle due e sono nel bersaglio, "pecora" e le tre e sono nel bersaglio "Sheeep". "E 2," non corrisponde a "set", perché "set" ha solo una "e".

N

Questo corrisponde esattamente a ripetizioni consecutive di un carattere precedente o di un gruppo precedente. Quindi il regex, "e 2" corrisponde alle due e sono nel bersaglio, "Sheep". "E 2" non corrisponde a "set" perché "set" ha solo una "e". Bene, "E 2" corrisponde a due e sono nel bersaglio, "Sheeep". C'è una sfumatura qui - vedi più tardi.

n, m

Ciò corrisponde a diverse ripetizioni consecutive di un carattere precedente o di un gruppo precedente, ovunque da N a M, compreso. Quindi, "E 1,3" non corrisponde a nulla in "Dig", che non ha "e". Abbina l'unico "E" in "Set", le due "E in" Sheep ", le tre e sono in" Sheeep "e tre" in "Sheeeep". C'è una sfumatura all'ultima partita - vedi più tardi.

Alternamento corrispondente

Considera la seguente stringa di destinazione nel computer.

“La fattoria ha maiali di diverse dimensioni."

Il programmatore potrebbe voler sapere se questo bersaglio ha "capra" o "coniglio" o "maiale". Il codice sarebbe il seguente:

char str [] = "La fattoria ha maiali di diverse dimensioni.";
if (regex_search (str, regex ("capra | coniglio | maiale")))
cout << "matched" << endl;
altro
cout << "not matched" << endl;

Il codice produce una corrispondenza. Nota l'uso del carattere di alternanza, |. Ci possono essere due, tre, quattro e più opzioni. C ++ proverà per la prima volta ad abbinare la prima alternativa, "capra", in ogni posizione del personaggio nella stringa di destinazione. Se non ha successo con "capra", prova la prossima alternativa, "Rabbit". Se non riesce a "Rabbit", prova la prossima alternativa, "maiale". Se "Pig" fallisce, allora C ++ passa alla posizione successiva nel bersaglio e inizia di nuovo con la prima alternativa.

Nel codice sopra, "maiale" è abbinato.

Inizio o fine corrispondente

Inizio


Se ^ è all'inizio del regex, allora il testo iniziale della stringa di destinazione può essere abbinato dal regex. Nel seguente codice, l'inizio dell'obiettivo è "ABC", che è abbinato:

if (regex_search ("ABC e def", regex ("^ABC")))
cout << "matched" << endl;

Nessuna corrispondenza ha luogo nel seguente codice:

if (regex_search ("Sì, ABC e def", regex ("^ABC")))
cout << "matched" << endl;
altro
cout << "not matched" << endl;

Qui, "ABC" non è all'inizio del bersaglio.

Nota: il carattere circonflesso, '^', è un metacharacter all'inizio del regex, corrispondente all'inizio della stringa di destinazione. È ancora un metacharacter all'inizio della classe del personaggio, dove nega la classe.

FINE

Se $ è alla fine del regex, il testo finale della stringa di destinazione può essere abbinato dal regex. Nel seguente codice, la fine del bersaglio è "XYZ", che è abbinata:

if (regex_search ("uvw e xyz", regex ("xyz $")))
cout << "matched" << endl;

Nessuna corrispondenza ha luogo nel seguente codice:

if (regex_search ("uvw e xyz final", regex ("xyz $")))
cout << "matched" << endl;
altro
cout << "not matched" << endl;

Qui, "xyz" non è alla fine del bersaglio.

Raggruppamento

Le parentesi possono essere usate per raggruppare i caratteri in uno schema. Considera il seguente regex:

"Un concerto (pianista)"

Il gruppo qui è "pianista" circondato dai metacharacter (e). In realtà è un sottogruppo, mentre "un concerto (pianista)" è l'intero gruppo. Considera quanto segue:

"Il (pianista è buono)"

Qui, il sottogruppo o la sotto-corda è "Pianista è buono".

Sertostrine con parti comuni

Un contabile è una persona che si prende cura dei libri. Immagina una biblioteca con un contabile e una libreria. Supponiamo che una delle seguenti stringhe target sia nel computer:

"La biblioteca ha una libreria ammirata.";
"Ecco il contabile.";
"Il contabile lavora con la libreria.";

Supponiamo che l'interesse del programmatore non sia quello di sapere quale di queste frasi sia nel computer. Tuttavia, il suo interesse è sapere se "scaffale" o "contabile" è presente in qualsiasi stringa target sia nel computer. In questo caso, il suo regex può essere:

"Bookshelf | contabile."

Usando l'alternanza.

Si noti che il "libro", che è comune a entrambe le parole, è stato digitato due volte, nelle due parole nel modello. Per evitare di digitare il "libro" due volte, il regex sarebbe meglio scritto come:

"Libro (scaffale | custode)"

Qui, il gruppo, "Shelf | Keeper" l'alternanza Metacharacter è ancora stato usato, ma non per due lunghe parole. È stato usato per le due parti finali delle due lunghe parole. C ++ tratta un gruppo come un'entità. Quindi, C ++ cercherà "scaffale" o "custode" che arriva immediatamente dopo il "libro". L'output del seguente codice è "abbinato":

char str [] = "La biblioteca ha una libreria ammirata.";
if (regex_search (str, regex ("libro (scaffale | custode)")))
cout << "matched" << endl;

"Bookshelf" e non "contabile" sono stati abbinati.

ICase e Multiline Regex_Constants

Icase

La corrispondenza è sensibile al caso per impostazione predefinita. Tuttavia, può essere reso insensibile al caso. Per raggiungere questo obiettivo, utilizzare la costante Regex :: Icase, come nel seguente codice:

if (regex_search ("feedback", regex ("feed", regex :: icase)))
cout << "matched" << endl;

L'output è "abbinato". Quindi il "feedback" con "F" maiuscola è stato abbinato da "feed" con "F" minuscolo. "Regex :: Icase" è stato fatto il secondo argomento del costruttore regex (). Senza questo, l'affermazione non produrrebbe una corrispondenza.

Multiline

Considera il seguente codice:

char str [] = "riga 1 \ nline 2 \ nline 3";
if (regex_search (str, regex ("^.*$ ")))
cout << "matched" << endl;
altro
cout << "not matched" << endl;

L'output è "non abbinato". Il regex, “^.*$ ”, Corrisponde alla stringa target dall'inizio alla sua fine. ".*"Significa qualsiasi carattere tranne \ n, zero o più volte. Quindi, a causa dei personaggi di Newline (\ n) nel bersaglio, non c'era corrispondenza.

L'obiettivo è una stringa multilinea. Per ".'Per abbinare il personaggio di Newline, deve essere fatto costante "Regex :: Multiline", il secondo argomento della costruzione Regex (). Il seguente codice illustra questo:

char str [] = "riga 1 \ nline 2 \ nline 3";
if (regex_search (str, regex ("^.*$ ", regex :: multiline)))
cout << "matched" << endl;
altro
cout << "not matched" << endl;

Corrispondere all'intera stringa di destinazione

Per abbinare l'intera stringa di destinazione, che non ha il carattere newline (\ n), è possibile utilizzare la funzione regex_match (). Questa funzione è diversa da regex_search (). Il seguente codice illustra questo:

char str [] = "primo secondo terzo";
if (regex_match (str, regex (".*secondo.*")))
cout << "matched" << endl;

C'è una partita qui. Tuttavia, si noti che il regex corrisponde all'intera stringa di destinazione e la stringa di destinazione non ha alcuna \ n '.

L'oggetto Match_Results

La funzione regex_search () può sostenere un argomento tra il bersaglio e l'oggetto regex. Questo argomento è l'oggetto match_results. L'intera stringa (parte) corrispondente e le sotto-corde abbinate possono essere conosciute con esso. Questo oggetto è un array speciale con metodi. Il tipo di oggetto Match_Results è cmatch (per i letterali di stringa).

Ottenere corrispondenze

Considera il seguente codice:

char str [] = "la donna che stavi cercando!";
cmatch m;
if (regex_search (str, m, regex ("w.M.N")))
cout << m[0] << endl;

La stringa target ha la parola "donna". L'output è "donna", che corrisponde al regex, "w.M.N". A Index Zero, l'array speciale contiene l'unica partita, che è "donna".

Con le opzioni di classe, solo la prima sotto-corda trovata nell'obiettivo, viene inviata all'array speciale. Il seguente codice illustra questo:

cmatch m;
if (regex_search ("Il ratto, il gatto, il pipistrello!", m, regex (" [bcr] at "))
cout << m[0] << endl;
cout << m[1] << endl;
cout << m[2] << endl;

L'output è "ratto" da indice zero. M [1] e M [2] sono vuoti.

Con alternative, solo la prima sotto-corda trovata nel bersaglio, viene inviata all'array speciale. Il seguente codice illustra questo:

if (regex_search ("Il coniglio, la capra, il maiale!", m, regex (" capra | coniglio | maiale "))
cout << m[0] << endl;
cout << m[1] << endl;
cout << m[2] << endl;

L'output è "coniglio" da indice zero. M [1] e M [2] sono vuoti.

Raggruppamenti

Quando i gruppi sono coinvolti, il modello completo abbinato, entra nella cella zero dell'array speciale. La prossima sotto-corda trovata va nella cella 1; Il seguito di sotto-corda, va nella cella 2; e così via. Il seguente codice illustra questo:

if (regex_search ("Best Bookseller oggi!", m, regex (" libro ((sel) (ler)) ")))
cout << m[0] << endl;
cout << m[1] << endl;
cout << m[2] << endl;
cout << m[3] << endl;

L'output è:

libraio
venditore
sel
ler

Si noti che il gruppo (venditore) viene prima del gruppo (SEL).

Posizione della corrispondenza

La posizione della corrispondenza per ogni sotto-corda nell'array di cmatch può essere nota. Il conteggio inizia dal primo carattere della stringa target, in posizione zero. Il seguente codice illustra questo:

cmatch m;
if (regex_search ("Best Bookseller oggi!", m, regex (" libro ((sel) (ler)) ")))
cout << m[0] << "->" << m.position(0) << endl;
cout << m[1] << "->" << m.position(1) << endl;
cout << m[2] << "->" << m.position(2) << endl;
cout << m[3] << "->" << m.position(3) << endl;

Nota l'uso della proprietà di posizione, con l'indice cellulare, come argomento. L'output è:

BOOKSELLER-> 5
venditore-> 9
Sel-> 9
ler-> 12

Cerca e sostituisci

Una nuova parola o frase può sostituire la partita. La funzione regex_replace () viene utilizzata per questo. Tuttavia, questa volta, la stringa in cui si verifica la sostituzione è l'oggetto stringa, non la stringa letterale. Quindi, la libreria String deve essere inclusa nel programma. Illustrazione:

#includere
#includere
#includere
Utilizzo dello spazio dei nomi std;
int main ()

String str = "qui, arriva il mio uomo. Ecco il tuo uomo.";
stringa newstr = regex_replace (str, regex ("uomo"), "donna");
cout << newStr << endl;
restituzione 0;

La funzione regex_replace (), come codificato qui, sostituisce tutte le partite. Il primo argomento della funzione è il bersaglio, il secondo è l'oggetto regex e il terzo è la stringa di sostituzione. La funzione restituisce una nuova stringa, che è l'obiettivo ma con la sostituzione. L'output è:

“Ecco la mia donna. Ecco la tua donna."

Conclusione

L'espressione regolare utilizza i pattern per abbinare i substringe nella stringa di sequenza target. I modelli hanno metacharacter. Funzioni comunemente usate per espressioni regolari C ++, sono: regex_search (), regex_match () e regex_replace (). Un regex è uno schema in doppia citazione. Tuttavia, queste funzioni prendono l'oggetto regex come argomento e non solo il regex. Il regex deve essere trasformato in un oggetto regex prima che queste funzioni possano usarlo.