MySQL Java JavaScript PHP Python HTML-CSS C-sharp

Expresii regulate

Clasele StringBuilder și String oferă funcționalitate suficientă pentru lucrul cu șiruri de caractere. Cu toate acestea, .NET oferă încă un instrument puternic - expresiile regulate. Expresiile regulate reprezintă o metodă eficientă și flexibilă pentru procesarea textelor mari, permițând în același timp reducerea semnificativă a volumului de cod comparativ cu utilizarea operațiilor standard cu șiruri.

Funcționalitatea principală a expresiilor regulate în .NET este concentrată în spațiul de nume System.Text.RegularExpressions. Clasa centrală pentru lucrul cu expresiile regulate este clasa Regex. De exemplu, avem un text și trebuie să găsim toate formele unui cuvânt. Cu clasa Regex, acest lucru se face foarte simplu:

using System.Text.RegularExpressions;

string s = "Boul cu buze groase, buzișoare groaznice, boul are buza albă groasă";
Regex regex = new Regex(@"gro(a*)");
MatchCollection matches = regex.Matches(s);
if (matches.Count > 0)
{
   foreach (Match match in matches)
       Console.WriteLine(match.Value);
}
else
{
   Console.WriteLine("Nu s-au găsit potriviri");
}

Aici găsim în șirul căutat toate formele cuvântului "groa". În constructorul obiectului Regex se transmite expresia regulată pentru căutare. Vom analiza mai departe câteva elemente ale sintaxei expresiilor regulate, dar deocamdată este suficient să știm că expresia gro(a*) înseamnă găsirea tuturor cuvintelor care au rădăcina "groa" și după care poate urma un număr variabil de caractere.

Expresia \w reprezintă un caracter alfanumeric, iar asteriscul după expresie indică un număr nedefinit de astfel de caractere - pot fi unul, două, trei sau deloc.

Metoda Matches a clasei Regex acceptă un șir, la care trebuie aplicate expresiile regulate, și returnează o colecție de potriviri găsite.

Fiecare element al acestei colecții reprezintă un obiect Match. Proprietatea sa Value returnează potrivirea găsită.

În acest caz, vom obține următoarea afișare în consolă:

groase
groaznice
groasă

Parametrul RegexOptions

Clasa Regex are o serie de constructori care permit inițializarea obiectului. Două versiuni ale constructorilor acceptă ca unul dintre parametri enumerarea RegexOptions. Câteva dintre valorile acceptate de această enumerare sunt:

  • Compiled: când este setată această valoare, expresia regulată este compilată într-o asamblare, ceea ce asigură o execuție mai rapidă
  • CultureInvariant: când este setată această valoare, vor fi ignorate diferențele regionale
  • IgnoreCase: când este setată această valoare, va fi ignorată diferența între majuscule și minuscule
  • IgnorePatternWhitespace: elimină spațiile din șir și permite comentarii care încep cu semnul #
  • Multiline: specifică că textul trebuie considerat în mod multiline. În acest mod, caracterele "^" și "$" se potrivesc cu începutul și sfârșitul oricărei linii, nu doar al întregului text
  • RightToLeft: specifică citirea șirului de la dreapta la stânga
  • Singleline: în acest mod, caracterul "." corespunde oricărui caracter, inclusiv secvenței "\n" care realizează trecerea la o linie nouă

De exemplu:

Regex regex = new Regex(@"gro(a*)", RegexOptions.IgnoreCase);

Dacă este necesar, putem seta mai mulți parametri:

Regex regex = new Regex(@"gro(a*)", RegexOptions.Compiled | RegexOptions.IgnoreCase);

Sintaxa expresiilor regulate

Să analizăm pe scurt câteva elemente ale sintaxei expresiilor regulate:

  • ^: potrivirea trebuie să înceapă la începutul șirului (de exemplu, expresia @"^cu\w*" se potrivește cuvântului "cuvânt" în șirul "cuvânt mare")
  • $: sfârșitul șirului (de exemplu, expresia @"\w*are$" se potrivește cuvântului "mare" în șirul "cuvânt mare", deoarece partea "are" se află la sfârșit)
  • .: punctul reprezintă orice caracter unic (de exemplu, expresia "c.v" se potrivește cuvântului "cuvânt" sau "cav")
  • *: caracterul anterior se repetă de 0 sau mai multe ori
  • +: caracterul anterior se repetă de 1 sau mai multe ori
  • ?: caracterul anterior se repetă de 0 sau 1 dată
  • \s: corespunde oricărui caracter de spațiu
  • \S: corespunde oricărui caracter care nu este spațiu
  • \w: corespunde oricărui caracter alfanumeric
  • \W: corespunde oricărui caracter non-alfanumeric
  • \d: corespunde oricărei cifre zecimale
  • \D: corespunde oricărui caracter care nu este o cifră zecimală

Aceasta este doar o mică parte a elementelor. O descriere mai detaliată a sintaxei expresiilor regulate poate fi găsită pe msdn în articolul "Regular Expression Language - Quick Reference".

Să vedem acum câteva exemple de utilizare. Să luăm primul exemplu cu "Boul cu buze groase, buzișoare groaznice, boul are buza albă groasă" și să găsim toate cuvintele în care apare rădăcina "buze":

string s = "Boul cu buze groase, buzișoare groaznice, boul are buza albă groasă";
Regex regex = new Regex(@"\w*buz\w*");

Deoarece expresia \w* corespunde oricărei secvențe de caractere alfanumerice de orice lungime, această expresie va găsi toate cuvintele care conțin rădăcina "buz".

Un alt exemplu simplu - găsirea unui număr de telefon în formatul 111-111-1111:

string s = "456-435-2318";
Regex regex = new Regex(@"\d{3}-\d{3}-\d{4}");

Dacă știm exact câte caractere trebuie să fie, putem specifica numărul lor explicit între acolade: \d{3} - în acest caz, trei cifre.

Putem nu doar să specificăm căutarea după anumite tipuri de caractere - spații, cifre, ci și să specificăm caracterele concrete care trebuie să apară în expresia regulată. De exemplu, să rescriem exemplul cu numărul de telefon și să specificăm clar ce caractere trebuie să conțină:

string s = "456-435-2318";
Regex regex = new Regex("[0-9]{3}-[0-9]{3}-[0-9]{4}");

Între paranteze pătrate se specifică intervalul de caractere care trebuie să apară în acel loc. În cele din urmă, acest șablon și șablonul anterior pentru numărul de telefon vor fi echivalente.

De asemenea, putem specifica intervale pentru caracterele alfabetice: Regex regex = new Regex("[a-v]{5}"); - această expresie va corespunde oricărei combinații de cinci caractere, în care toate caracterele se află în intervalul de la a la v.

Putem specifica și valori individuale: Regex regex = new Regex(@"[2]*-[0-9]{3}-\d{4}");. Această expresie va corespunde, de exemplu, unui număr de telefon "222-222-2222" (deoarece primele cifre sunt doi).

Cu ajutorul operatorului | putem specifica caractere alternative, de exemplu:

Regex regex = new Regex(@"(2|3){3}-[0-9]{3}-\d{4}");

Adică primele trei cifre pot conține doar doi sau trei. Un astfel de șablon va corespunde, de exemplu, șirurilor "222-222-2222" și "323-435-2318". Dar șirul "235-435-2318" nu se va potrivi șablonului, deoarece una dintre primele trei cifre este cinci.

Astfel, caracterele precum *, + și altele sunt folosite ca simboluri speciale. Și apare întrebarea, ce facem dacă trebuie să găsim șiruri care conțin punct, asterisc sau alt simbol special? În acest caz, trebuie doar să scăpăm aceste caractere cu un backslash:

Regex regex = new Regex(@"(2|3){3}\.[0-9]{3}\.\d{4}");
// această expresie va corespunde șirului "222.222.2222"

Verificarea formatului șirului

Adesea, trebuie să verificăm corectitudinea datelor introduse de utilizator. Aceasta poate fi verificarea unei adrese de email, a unui număr de telefon, etc. Clasa Regex oferă metoda statică IsMatch, care permite verificarea unui șir cu un șablon:

using System.Text.RegularExpressions;

string pattern = @"^(?("")(""[^""]+?""@)|(([0-9a-z]((\.(?!\.))|[-!#\$%&'\*\+/=\?\^\{\}\|~\w])*)(?<=[0-9a-z])@))" +
               @"(?(\[)(\[(\d{1,3}\.){3}\d{1,3}\])|(([0-9a-z][-\w]*[0-9a-z]*\.)+[a-z0-9]{2,17}))$";
var data = new string[]
{
   "tom@gmail.com",
   "+12345678999",
   "bob@yahoo.com",
   "+13435465566",
   "sam@yandex.ru",
   "+43743989393"
};

Console.WriteLine("Email List");
for(int i = 0; i < data.Length; i++)
{
   if (Regex.IsMatch(data[i], pattern, RegexOptions.IgnoreCase))
   {
       Console.WriteLine(data[i]);
   }
}

Variabila pattern specifică expresia regulată pentru verificarea adresei de email. Această expresie este oferită de Microsoft pe paginile msdn.

Apoi, în ciclul for, parcurgem tabloul de șiruri și determinăm care șiruri corespund acestui șablon, adică reprezintă o adresă de email validă. Pentru verificarea corespondenței unui șir cu un șablon, se folosește metoda IsMatch:

Regex.IsMatch(data[i], pattern, RegexOptions.IgnoreCase). Ultimul parametru indică faptul că diferențele de majuscule/minuscule pot fi ignorate. Și dacă șirul corespunde șablonului, metoda returnează true.

Înlocuirea și metoda Replace

Clasa Regex are metoda Replace, care permite înlocuirea unui șir ce corespunde expresiei regulate cu un alt șir:

string text = "Mama spăla geamul.";
string pattern = @"\s+";
string target = " ";
Regex regex = new Regex(pattern);
string result = regex.Replace(text, target);
Console.WriteLine(result);

Această versiune a metodei Replace primește doi parametri: șirul cu textul unde trebuie făcută înlocuirea și șirul de înlocuire. Deoarece șablonul ales este expresia "\s+ (adică unul sau mai multe spații), metoda Replace parcurge tot textul și înlocuiește spațiile consecutive cu unul singur.

Un alt exemplu - se dă un număr de telefon în format arbitrar și dorim să păstrăm doar cifrele:

string phoneNumber = "+1(876)-234-12-98";
string pattern = @"\D";
string target = "";
Regex regex = new Regex(pattern);
string result = regex.Replace(phoneNumber, target);
Console.WriteLine(result); // 18762341298

În acest caz, șablonul "\D" reprezintă orice caracter care nu este cifră. Orice astfel de caracter este înlocuit cu un șir gol "", adică în final din șirul "+1(876)-234-12-98" obținem șirul "18762341298".

← Lecția anterioară Lecția următoare →