This article has been localized into Czech by the community.
Vyhledávání s třídou Regex
Jak jsme diskutovali v předchozím článku, regulární výrazy umožňují definovat vyhledávací vzory pro práci s řetězci. Pro zpracování těchto vyhledávacích vzorů přichází s .NET frameworkem a velmi univerzální třídou: Třída Regex. V tomto článku definujeme některé vyhledávací vzory a použijeme je s třídou Regex, ale mějte prosím na paměti, že syntaxe regulárních výrazů může být docela komplikovaná a že toto je tutoriál C# a ne tutoriál regulárních výrazů. Místo toho použiji některé jednoduché vzory regulárních výrazů, abych demonstroval, jak s nimi pracovat v C#. Pokud chcete vědět více o regulárních výrazech, doporučuji tento tutoriál regulárních výrazů.
Metoda IsMatch()
V tomto prvním příkladu použiji jednu z nejzákladnějších metod třídy Regex nazvanou IsMatch. Jednoduše vrací true nebo false v závislosti na tom, zda byly ve zkoušeném řetězci nalezeny jeden nebo více shod:
string testString = "John Doe, 42 years";
Regex regex = new Regex("[0-9]+");
if (regex.IsMatch(testString))
Console.WriteLine("String contains numbers!");
else
Console.WriteLine("String does NOT contain numbers!");
Definujeme testovací řetězec a pak vytvoříme instanci třídy Regex. Předáme skutečný regulární výraz jako řetězec - v tomto případě regex specifikuje, že hledáme číslo libovolné délky. Poté vypíšeme řádek textu v závislosti na tom, zda regex odpovídá našemu testovacímu řetězci. Docela cool, ale ve většině případů chcete s nalezenými shodami skutečně něco udělat - pro to máme třídu Match.
Třída Match a metoda
V tomto dalším příkladu zachytíme číslo nalezené v testovacím řetězci a představíme ho uživateli, místo abychom pouze ověřili, že tam je:
string testString = "John Doe, 42 years";
Regex regex = new Regex("[0-9]+");
Match match = regex.Match(testString);
if (match.Success)
Console.WriteLine("Number found: " + match.Value);
Používáme stejný regex a testovací řetězec jako dříve. Volám metodu Match(), která vrátí instanci třídy Match - to se stane, ať už byla shoda nalezena nebo ne. Abych si byl jistý, že byla shoda nalezena, zkontroluji vlastnost Success. Jakmile jsem si jistý, že byla shoda nalezena, použiji vlastnost Value k jejímu získání.
Třída Match obsahuje více užitečných informací než jen nalezený řetězec - například můžete snadno zjistit, kde byla shoda nalezena, jak dlouhá je a tak dále:
string testString = "John Doe, 42 years";
Regex regex = new Regex("[0-9]+");
Match match = regex.Match(testString);
if (match.Success)
Console.WriteLine("Match found at index " + match.Index + ". Length: " + match.Length);
Vlastnosti Index a Délka jsou zde použity k zobrazení informací o umístění a délce shody.
Skupiny zachycení
V prvních několika příkladech jsme našli jen jednu hodnotu v našem hledaném řetězci, ale regulární výrazy mohou samozřejmě udělat mnohem více než to! Například můžeme najít jak jméno, tak věk v našem testovacím řetězci, zatímco nezajímavé části, jako je příkaz a text "let", ignorujeme. Dělat něco takového je pro regulární výrazy hračka, ale pokud nejste obeznámeni se syntaxí, může to vypadat velmi komplikovaně, ale pojďme to stejně zkusit:
string testString = "John Doe, 42 years";
Regex regex = new Regex(@"^([^,]+),\s([0-9]+)");
Match match = regex.Match(testString);
if (match.Success)
Console.WriteLine("Name: " + match.Groups[1].Value + ". Age: " + match.Groups[2].Value);
Upravil jsem regulární výraz tak, aby hledal cokoli, co není čárka - tato hodnota je umístěna do první skupiny zachycení díky okolním závorkám. Poté hledá oddělující čárku a poté číslo, které je umístěno do druhé skupiny zachycení (opět díky okolním závorkám). Na posledním řádku používám vlastnost Groups k přístupu k odpovídajícím skupinám. Používám index 1 pro jméno a 2 pro věk, protože to odpovídá pořadí, ve kterém byly skupiny shod definovány ve výrazu regex (index 0 obsahuje celou shodu).
Pojmenované skupiny zachycení
Jakmile regulární výraz stane se složitějším/delším než ten, který jsme právě použili, číslované skupiny zachycení se mohou stát nepřehlednými, protože si neustále musíte pamatovat jejich pořadí a indexy. Naštěstí regulární výrazy a .NET framework podporují pojmenované skupiny zachycení, což vám umožní každé skupině dát název ve výrazu regex a poté na ni odkazovat ve vlastnosti Groups. Podívejte se na tento přepracovaný příklad, kde používáme pojmenované skupiny místo číslovaných:
string testString = "John Doe, 42 years";
Regex regex = new Regex(@"^(?<name>[^,]+),\s(?<age>[0-9]+)");
Match match = regex.Match(testString);
if (match.Success)
Console.WriteLine("Name: " + match.Groups["name"].Value + ". Age: " + match.Groups["age"].Value);
Funguje to přesně jako předtím, ale nyní můžete použít logické názvy pro vyhledávání odpovídajících hodnot místo toho, abyste si museli pamatovat správný index. To nemusí být velký rozdíl v našem jednoduchém příkladu, ale jak bylo zmíněno, určitě to oceníte, když vaše regulární výrazy narostou na složitosti a délce.
Třída MatchCollection
Třída Match je tím správným řešením, pokud chcete pracovat pouze s jedním shodným výsledkem (pamatujte, že shoda může obsahovat více hodnot, jak jsme viděli v předchozích příkladech), ale někdy chcete pracovat s několika shodami najednou. Pro to máme metodu Matches(), která vrátí třídu MatchCollection. Obsahovat bude všechny shodné hodnoty v pořadí, ve kterém byly nalezeny. Podívejme se, jak ji lze použít:
string testString = "123-456-789-0";
Regex regex = new Regex(@"([0-9]+)");
MatchCollection matchCollection = regex.Matches(testString);
foreach (Match match in matchCollection)
Console.WriteLine("Number found at index " + match.Index + ": " + match.Value);
Změnil jsem regulární výraz a testovací řetězec ve srovnání s předchozími příklady. Nyní máme testovací řetězec, který obsahuje několik čísel, a regulární výraz, který specificky hledá řetězce skládající se z jednoho nebo více čísel. Používáme metodu Matches() pro získání MatchCollection z našeho regulárního výrazu, která obsahuje shody nalezené v řetězci. V tomto případě existují čtyři shody, které vypisujeme jednu po druhé pomocí cyklu foreach. Výsledek bude vypadat nějak takto:
Number found at index 0: 123
Number found at index 4: 456
Number found at index 8: 789
Number found at index 12: 0
Pokud nebyly nalezeny žádné shody, byla by vrácena prázdná kolekce MatchCollection.
Shrnutí
S pomocí třídy Regex, společně s třídami Match a MatchCollection, můžeme snadno provádět velmi pokročilé porovnávání řetězců. Syntaxe regulárních výrazů se může zdát velmi složitá, ale jakmile se ji naučíte, budete mít k dispozici velmi silný nástroj. I když nechcete investovat čas do učení se syntaxe regulárních výrazů, často můžete najít výrazy pro konkrétní potřeby, které vytvořili jiní programátoři, jednoduchým vyhledáváním na Google. Jakmile máte napsaný nebo půjčený řetězec regulárního výrazu, můžete jej použít pro své vlastní účely s technikami a třídami ukázanými v tomto článku.
Ale vyhledávání je jen část zábavy - s regulárními výrazy můžete také provádět některé velmi cool vyhledávací/nahrazovací operace. Podíváme se na to v jednom z dalších článků.