Регулярные выражения

Регулярные выражения — это специализированный язык шаблонов для обработки текста. Он позволяет описывать правила поиска, проверки, извлечения и замены фрагментов строк. С его помощью можно искать и извлекать фрагменты текста, проверять формат строк и выполнять сложные замены.

В PascalABC.NET регулярные выражения задаются обычными строками, например '\d+', '\w+', '\bкот\b'.

Основные операции доступны как методы строк: IsMatch, MatchValue, MatchValues, Matches, RegexReplace.

Проверка соответствия

Метод IsMatch проверяет, содержит ли строка фрагмент, соответствующий регулярному выражению.

begin
  var s := 'abc123';

  Println(s.IsMatch('\d+'));
  Println(s.IsMatch('[A-Z]+'));
end.

Результат:

True
False

Первое совпадение

Метод MatchValue возвращает первое найденное совпадение в виде строки.

begin
  var s := 'Цена 120 рублей, скидка 15 процентов';

  Println(s.MatchValue('\d+'));
end.

Результат:

120

Все совпадения

Метод MatchValues возвращает все найденные совпадения как последовательность строк.

begin
  var s := 'Цена 120 рублей, скидка 15 процентов';

  s.MatchValues('\d+').Println;
end.

Результат:

120 15

Позиции найденных фрагментов

Метод Matches возвращает последовательность объектов Match, содержащих найденный текст, его позицию и длину.

begin
  var s := 'red green blue';

  foreach var m in s.Matches('\w+') do
    Println(m.Value, m.Index, m.Length);
end.

Результат:

red 0 3
green 4 5
blue 10 4

Классы символов

В регулярных выражениях можно задавать классы символов: \d — цифра, \w — буква, цифра или _, \s — пробельный символ.

begin
  var s := 'abc 123 45.6';

  s.MatchValues('\d+').Println;
  s.MatchValues('\w+').Println;
end.

Результат:

123 45 6
abc 123 45 6

Классы символов можно задавать и явно:

begin
  var s := 'cat cot cut cit';

  s.MatchValues('c[ao]t').Println;
end.

Результат:

cat cot

Квантификаторы

Квантификаторы задают количество повторений предыдущего элемента шаблона.

*       0 или более
+       1 или более
?       0 или 1
{n}     ровно n
{n,}    не менее n
{n,m}   от n до m

Например, найдём числа, содержащие от двух до четырёх цифр.

begin
  var s := '7 12 345 6789 12345';

  s.MatchValues('\b\d{2,4}\b').Println;
end.

Результат:

12 345 6789

Альтернатива и набор символов

Символ | задаёт выбор между вариантами, а квадратные скобки — выбор одного символа из набора.

begin
  var s := 'кот кит кат крот';

  s.MatchValues('кот|кит').Println;
  s.MatchValues('к[ио]т').Println;
end.

Результат:

кот кит
кот кит

Граница слова

Последовательность \b обозначает границу слова. С помощью Matches можно увидеть не только найденные фрагменты, но и их позиции в строке.

begin
  var s := 'бойкот котомка кот';

  foreach var m in s.Matches('\bкот') do
    Println(m.Value, m.Index);
  Println;
  foreach var m in s.Matches('кот\b') do
    Println(m.Value, m.Index);
  Println;
  foreach var m in s.Matches('\bкот\b') do
    Println(m.Value, m.Index);
end.

Результат:

кот 7
кот 15

кот 3
кот 15

кот 15

Игнорирование регистра

Опция RegexOptions.IgnoreCase позволяет выполнять поиск без учёта регистра символов.

begin
  var s := 'PaScal PASCAL pascal Python';

  s.MatchValues('pascal', RegexOptions.IgnoreCase).Println;
end.

Результат:

PaScal PASCAL pascal

Простая замена

Метод RegexReplace заменяет все фрагменты, соответствующие регулярному выражению.

begin
  var s := 'один   два    три';

  Println(s.RegexReplace(' +', ' '));
end.

Результат:

один два три

Замена найденного фрагмента

В строке замены $0 обозначает всё найденное совпадение.

begin
  var s := 'один два три';

  Println(s.RegexReplace('\w+', '<$0>'));
end.

Результат:

<один> <два> <три>

Замена с группами

Круглые скобки создают группы, а $1, $2, $3 позволяют использовать найденные группы в строке замены.

begin
  var s := '2026/08/16';

  s := s.RegexReplace(
    '(\d{4})/(\d{2})/(\d{2})',
    '$3.$2.$1'
  );

  Println(s);
end.

Результат:

16.08.2026

Замена с лямбдой

Вместо строки замены можно передать лямбда-выражение, вычисляющее новое значение для каждого совпадения.

begin
  var s := 'один два четыре';

  Println(
    s.RegexReplace(
      '\w+',
      m -> $'{m.Value}({m.Length})'
    )
  );
end.

Результат:

один(4) два(3) четыре(6)

Вычисляемая замена

Лямбда позволяет использовать найденные группы и выполнять вычисления при замене.

begin
  var s := '10+2 5+31 777+333';

  var result := s.RegexReplace(
    '(\d+)\+(\d+)',
    m -> (
      m.Groups[1].Value.ToInteger +
      m.Groups[2].Value.ToInteger
    ).ToString
  );

  Println(result);
end.

Результат:

12 36 1110

Жадный и ленивый поиск

По умолчанию квантификаторы стараются захватить как можно больше символов; добавление ? делает их ленивыми.

begin
  var s := '"one" and "two"';

  s.MatchValues('".*"').PrintLines;
  s.MatchValues('".*?"').PrintLines;
end.

Результат:

"one" and "two"
"one"
"two"

Положительный просмотр вперёд

Конструкция (?=...) проверяет, что после найденного фрагмента следует заданный шаблон, но не включает его в результат. В данном примере ищутся все слова, после которых идет запятая.

begin
  var s := 'Привет, как дела, что нового?';

  s.MatchValues('\b\w+\b(?=,)').Println;
end.

Результат:

Привет дела

Отрицательный просмотр назад

Конструкция (?<=...) проверяет, что перед найденным фрагментом находится заданный шаблон, но не включает его в результат. В данном примере ищутся все цены в долларах.

begin
  var s := 'Цены: $100, $200, 300 рублей';

  s.MatchValues('(?<=\$)\d+').Println;
end.

Результат:

100 200