Регулярные выражения
Регулярные выражения — это специализированный язык шаблонов для обработки текста. Он позволяет описывать правила поиска, проверки, извлечения и замены фрагментов строк.
С помощью регулярных выражений можно искать и извлекать фрагменты текста, проверять формат строк и выполнять сложные замены.
В 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.
Результат:
один два три
Замена найденного фрагмента
Метод RegexReplace заменяет все фрагменты строки, соответствующие регулярному выражению.
В строке замены можно использовать специальные обозначения найденных фрагментов. $0 означает всё найденное совпадение целиком.
begin
var s := 'один два три';
Println(s.RegexReplace('\w+', '<$0>'));
end.
Результат:
<один> <два> <три>
Здесь регулярное выражение \w+ находит каждое слово, а строка замены <$0> помещает найденное слово между символами < и >.
Замена с группами
Круглые скобки создают группы, а выражения $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"
В выражении ".*" часть .* жадно захватывает всё от первой до последней кавычки.
В выражении ".*?" квантификатор *? работает лениво, поэтому поиск останавливается на ближайшей закрывающей кавычке. В результате находятся две отдельные строки: "one" и "two".
Положительный просмотр вперёд
Конструкция (?=...) выполняет положительный просмотр вперёд: она проверяет, что после найденного фрагмента следует заданный шаблон, но не включает его в результат.
В данном примере ищутся все слова, после которых идет запятая.
begin
var s := 'Привет, как дела, что нового?';
s.MatchValues('\b\w+\b(?=,)').Println;
end.
Результат:
Привет дела
Выражение \w+ находит слово, а (?=,) проверяет наличие запятой сразу после него. Запятая при этом не входит в найденный фрагмент.
Положительный просмотр назад
Конструкция (?<=...) выполняет положительный просмотр назад: она проверяет, что перед найденным фрагментом находится заданный шаблон, но не включает его в результат.
В данном примере ищутся числа, перед которыми стоит знак доллара.
begin
var s := 'Цены: $100, $200, 300 рублей';
s.MatchValues('(?<=\$)\d+').Println;
end.
Результат:
100 200
Выражение \d+ находит число, а (?<=\$) проверяет, что непосредственно перед ним находится символ $.
Символ $ в регулярных выражениях имеет специальное значение, поэтому перед ним ставится символ экранирования \.