Aceasta este o parte din două serii de tutoriale despre expresii regulate în Go. În prima parte am învățat ce expresii regulate sunt, cum să le exprimi în Go și elementele de bază ale utilizării bibliotecii Go regexp pentru a potrivi textul cu modelele de expresie obișnuită.
În cea de-a doua parte, ne vom concentra pe folosirea în întregime a bibliotecii regexp, incluzând compilarea expresiilor regulate, găsirea unuia sau mai multor meciuri în text, înlocuirea expresiilor regulate, gruparea submatriculelor și tratarea liniilor noi.
Biblioteca regexp oferă suport complet pentru expresii regulate, precum și abilitatea de a vă compila modelele pentru o execuție mai eficientă atunci când utilizați același model pentru a se potrivi cu mai multe texte. De asemenea, puteți găsi indicii de potrivire, înlocuiți potrivirile și utilizați grupuri. Hai să ne aruncăm.
Există două metode pentru compilarea regexelor: Compila()
și MustCompile ()
. Compila()
va întoarce o eroare dacă modelul furnizat este nevalid. MustCompile ()
va panica. Compilarea este recomandată dacă vă interesează performanța și intenționați să utilizați același regiștru de mai multe ori. Să ne schimbăm Meci()
funcția helper pentru a obține o regiștină compilată. Rețineți că nu este nevoie să verificați erorile deoarece regexul compilat trebuie să fie valabil.
funcția potrivită (r * regexp.Regexp, șir de text) matched: = r.MatchString (text) dacă este potrivită fmt.Println ("√", r.String (),:; Println ("X", r.String (), ":", text)
Iată cum puteți să compilați și să utilizați același regiștru compilat de mai multe ori:
func principale () es: = '(\ bcats? \ b) | (\ bdogs? \ b) | (brats? \ b)' e: = regexp.MustCompile și pisicile) (e, "Catalogul este gata, este timpul hotdog!") (e, "Este un câine mănâncă lumea câinilor.") Ieșire: √ (bcats? \ b) | (brats? \ b): Câinii și pisicile plouă X (\ bcats? \ b) | (\ brats? \ b): Catalogul este gata. E timpul hotdog! √ (\ bcats? \ B) | (\ bdogs? \ B) | (brats? B): Este un câine mănâncă câine lume.
Obiectul Regexp are a mult de FindXXX ()
metode. Unii dintre ei returnează primul meci, ceilalți returnează toate meciurile și totuși ceilalți întorc un index sau indexuri. În mod interesant, numele tuturor celor 16 metode de funcții se potrivesc cu următorul regex: Găsiți (Toate)? (String)? (Submatch)? (Index)?
Dacă este prezentă "Toate", toate meciurile sunt returnate față de cel din stânga. Dacă este prezentă "String", atunci textul țintă și valorile de întoarcere sunt șiruri în raport cu arhitecturile byte. Dacă este prezent "Submatch", atunci submatriculele (grupurile) sunt returnate vs. meciuri simple. Dacă este prezentă "Index", indexurile din textul țintă sunt returnate față de potrivirile reale.
Să luăm una dintre cele mai complexe funcții pentru sarcină și utilizare FindAllStringSubmatch ()
metodă. Este nevoie de un șir și un număr n
. Dacă n
este -1, va returna toți indicii potriviți. Dacă n este un număr întreg negativ, atunci se va întoarce n nulile din stânga. Rezultatul este o felie de felii de sfoară.
Rezultatul fiecărui submăsură este potrivirea completă urmată de grupul capturat. De exemplu, luați în considerare o listă de nume unde unele dintre ele au titluri precum "domnul", "doamna" sau "dr.". Aici este un regex care captează titlul ca submatch și apoi restul numelui după un spațiu: \ b (d-nă | doamnă | dr.). *
.
functie principala () re: = regexp.MustCompile ('\ b (Mr \. | Mrs \. | Dr \.).') fmt.Println (" fmt.Println (re.FindAllStringSubmatch ("doamna Doubtfire Mr. Anderson", -1)) Rezultat: [[Dr. Dolittle Dr.]] [[D-na. Doubtfire Doamna] [domnul Anderson Mr.]]
După cum puteți vedea în ieșire, se va reține mai întâi întregul meci și apoi doar titlul. Pentru fiecare rând, căutarea se resetează.
Găsirea meciurilor este minunată, însă de cele mai multe ori poate fi necesar să înlocuiți meciul cu altceva. Obiectul Regexp are mai multe ReplaceXXX ()
metode obișnuite pentru a trata cu șiruri vs. seturi de octeți și înlocuiri literale vs. expansiuni. În marea carte 1984 de George Orwell, sloganurile partidului sunt înscrise pe piramida albă a lucrării adevărului:
Am găsit un eseu despre Prețul Libertății care folosește unii dintre acești termeni. Să corectăm un fragment dintr-un duplicat de partid folosind Go regexes. Rețineți că unele dintre cuvintele țintă pentru înlocuire folosesc diferite capitalizare. Soluția este să adăugați pavilionul insensibil pentru litere mici (I?)
la începutul regelui.
Deoarece traducerea este diferită în funcție de caz, avem nevoie de o abordare mai sofisticată, apoi înlocuirea literală. Din fericire (sau prin design), obiectul Regexp are o metodă de înlocuire care acceptă o funcție pe care o folosește pentru a efectua înlocuirea reală. Să definim funcția înlocuitorului care returnează traducerea cu cazul corect.
funcția "război": "pace", "război": "pace", "război": "pace", "libertate" FREEDOM ":" SLAVERY "," Libertate ":" Sclavie "," ignoranță ":" putere "," IGNORANȚĂ ":" STRENGTH "," Ignoranță ":" Forță "; ok return r altceva return s
Acum, putem efectua înlocuirea reală:
func main () PRETUL LIBERTĂȚII: americanii de la război americanii au plecat la război pentru a-și câștiga independența, pentru a-și extinde granițele naționale, a-și defini libertățile și a-și apăra interesele în întreaga lume. (r): () (r) (război | libertate | ignoranță) r: = regexp.MustCompile (expr) rezultat: = r.ReplaceAllStringFunc (rezultat, Americanii de la pacii americani au mers în pace pentru a-și câștiga independența, a-și extinde granițele naționale, a-și defini sclavi și a-și apăra interesele în întreaga lume.
Rezultatul este oarecum incoerent, care este semnul distinctiv al propagandei bune.
Am văzut cum să folosim gruparea cu submatches mai devreme. Dar este uneori dificil să se ocupe de mai multe submatches. Grupurile numite pot ajuta foarte mult aici. Iată cum puteți numi grupurile dvs. de submatch și puteți popula un dicționar pentru un acces ușor după nume:
func principal () e: = '(? P\ w +) (p .+ )? (? P \ w +) 'r: = regexp.MustCompile () nume: = r.SubexpNames () fullNames: = [] șir ' John F. Kennedy ',' Michael Jordan ' pentru _, fullName: : = r.FindAllStringSubmatch (numeNumar, -1) m: = harta [string] string pentru i, n: = rezultatul intervalului [0] m [nume [i]] = n fmt.Println : fmt.Println ("middle_name:", m ["middle"]) fmt.Println ("last name", m ["last"]) Ieșire: Prenume: John middle_name: F. Nume: Kennedy Prenume: Michael Nume de mijloc: Prenume: Jordan
Dacă vă aduceți aminte, am spus că caracterul special al punctului se potrivește cu orice personaj. L-am mințit. Nu se potrivește cu linia nouă (\ n
) în mod prestabilit. Aceasta înseamnă că meciurile dvs. nu vor trece linii decât dacă le specificați în mod explicit cu steagul special (? S)
pe care le puteți adăuga la începutul regelui dvs. Iată un exemplu cu și fără steag.
()) pentru "_, e: = interval expr r: = regexp.MustCompile () e) rezultă: = r.FindString (text) rezultat = șiruri de caractere.Replace (rezultat, "\ n", '\ n', -1) fmt.Println (e, Ieșire:. *: 1111 (? S). *: 1111 \ n2222
O altă întrebare este dacă trebuie tratată ^
și $
caractere speciale ca începutul și sfârșitul întregului text (implicit) sau ca începutul și sfârșitul fiecărei linii cu (? M)
steag.
Expresiile regulate sunt un instrument puternic atunci când lucrați cu text semistructurat. Aveți posibilitatea să le utilizați pentru a valida intrarea textuală, ao curăța, ao transforma, o normaliza și, în general, se ocupă de o multitudine de diversitate folosind sintaxa concisă.
Go oferă o bibliotecă cu o interfață ușor de utilizat, care constă dintr-un obiect Regexp cu multe metode. Faceți o încercare, dar aveți grijă de capcane.