Регулярные выражения на C#
У меня есть алфавит {a,b,c}. Для него нужно составить регулярное выражение по предложению "Произвольная цепочка символов a, b и c, заканчивающаяся символами сс".
По идее это (a|b|c)*(cc)
Но проверка через Regex.IsMatch выводит мне и слова, начинающиеся с cc
using System;
using System.Text.RegularExpressions;
class Program
{
static char[] alphabet = { 'a', 'b', 'c' };
static List<string> GenerateWords(int n)
{
List<string> words = new();
int alphabetSize = alphabet.Length;
int[] indices = new int[n];
for (int i = 0; i < n; i++)
{
// Convert index to base-alphabet and append corresponding letters
string word = "";
int index = i;
while (index > 0)
{
int remainder = index % alphabetSize;
word = alphabet[remainder] + word;
index /= alphabetSize;
}
while (word.Length < 1)
{
word = alphabet[0] + word;
}
Console.WriteLine(word);
words.Add(word);
}
return words;
}
static void FindRegex(List<string> words, string finalChars)
{
string regex = "(";
for (int i= 0;i<alphabet.Length;i++)
{
regex += alphabet[i];
if (i != alphabet.Length - 1) regex += '|';
}
regex += ")*(" + finalChars+')';
Console.WriteLine("Regular expression: " + regex);
List<string> matchingWords = new List<string>();
foreach (string word in words)
{
if (Regex.IsMatch(word, regex))
{
matchingWords.Add(word);
}
}
if (matchingWords.Count == 0) Console.WriteLine("Words not found or final symbols are not contained in this alphabet");
else
{
Console.WriteLine("Matching words: ");
foreach (string word in matchingWords)
{
Console.WriteLine(word);
}
}
}
static void Main(string[] args)
{
List<string> words= GenerateWords(30);
FindRegex(words, "cc");
}
}
Ответы (1 шт):
В регулярном выражении не указано, что не может быть других символов.
Таким образом выбранные строки вполне подходят под выражение: пустая последовательность a|b|c после которой идет cc.
Для исправления достаточно указать $ который сопоставляется с концом строки, чтобы явно указать, что cc должны быть именно у конца строки.
Также можно добавить ^, для указания что и спереди ничего не должно быть
^(a|b|c)*cc$
небольшое отступление: цикл
for (int i= 0;i<alphabet.Length;i++)
{
regex += alphabet[i];
if (i != alphabet.Length - 1) regex += '|';
}
Легко меняется на string.Join: string.Join("|", alphabet)
И общая сборка выражения упрощается до:
regex = `({string.Join("|", alphabet)})*{finalChars}`;
