Замены через s/// и захваты через ()
В прошлом уроке мы научились искать совпадения по шаблону. Но регулярки умеют и больше — заменять найденный текст на другой. Это одна из самых частых задач в реальной работе: почистить лишние пробелы, поменять формат даты, скрыть часть номера карты звёздочками. Для этого в Perl есть оператор замены s///.
Оператор s///
Буква s означает substitute, «заменить». Синтаксис такой: s/шаблон/замена/. Слэши здесь разделяют три части оператора на две секции: что искать и на что менять. Оператор применяется через уже знакомый нам =~.
my $greeting = "Привет, Мир!";
$greeting =~ s/Мир/Perl/;
print "$greeting\n";Вывод:
Привет, Perl!Здесь мы ищем в переменной $greeting слово «Мир» и заменяем его на «Perl». Важная деталь: оператор s/// изменяет саму переменную $greeting — это происходит «на месте», в отличие от многих других языков, где обычно приходится создавать новую строку. Именно поэтому слева от =~ должна стоять переменная, а не просто текстовое значение.
По умолчанию s/// заменяет только первое найденное совпадение. Если в строке слово встречается несколько раз, а поменять нужно все — понадобится флаг g, который мы разберём в следующем уроке.
Группы захвата: скобки как «карманы»
Самое мощное в регулярках — это группы захвата. Если часть шаблона обернуть в круглые скобки, Perl запоминает, что именно туда попало, и кладёт это в специальные переменные $1, $2, $3 и так далее — по порядку скобок слева направо.
my $date = "25-12-2026";
if ($date =~ /(\d{2})-(\d{2})-(\d{4})/) {
print "День: $1\n";
print "Месяц: $2\n";
print "Год: $3\n";
}Вывод:
День: 25
Месяц: 12
Год: 2026Разберём шаблон (\d{2})-(\d{2})-(\d{4}). Первая пара скобок ловит две цифры (день), потом идёт литеральный дефис, вторая пара скобок ловит ещё две цифры (месяц), снова дефис, и третья пара скобок ловит четыре цифры (год). После успешного совпадения переменная $1 хранит содержимое первой группы, $2 — второй, $3 — третьей. Эти переменные живут до следующего совпадения, так что пользоваться ими нужно сразу после проверки.
Использование захватов в замене
Самая полезная комбинация — использовать группы захвата не только при поиске, но и в самой строке замены. Например, чтобы поменять формат даты с «день-месяц-год» на «год/месяц/день»:
my $date = "25-12-2026";
$date =~ s/(\d{2})-(\d{2})-(\d{4})/$3\/$2\/$1/;
print "$date\n";Вывод:
2026/12/25Здесь в части «на что менять» мы используем $1, $2, $3 — то, что было захвачено при поиске. Обратите внимание: слэш внутри замены пришлось экранировать как \/, потому что обычный слэш — это разделитель частей оператора s///, и Perl мог бы принять его за конец шаблона.
Это невероятно удобно для переформатирования текста: захватываем нужные куски по отдельности, а потом просто расставляем их в новом порядке в замене.
Мини-пример: маскировка номера карты
Соберём то, что узнали, в практическую задачу — скрыть все цифры номера банковской карты, кроме последних четырёх:
my $card = "4276 1234 5678 9012";
$card =~ s/(\d{4} \d{4} \d{4}) (\d{4})/**** **** **** $2/;
print "$card\n";Вывод:
**** **** **** 9012Первая группа захватывает первые три блока цифр целиком (но мы её даже не используем в замене — просто «поглощаем» ненужную часть), а вторая группа сохраняет последний блок, чтобы вставить его обратно через $2. Остальную часть заменяем на звёздочки прямо текстом.
Частые ошибки
Частая ошибка — забыть, что $1, $2 и так далее «живут» только после успешного совпадения. Если проверка совпадения провалилась (например, внутри if, который не выполнился), то использование $1 дальше в коде вернёт мусор или значение от предыдущего совпадения — это может привести к незаметным багам.
Ещё одна ошибка — путать нумерацию скобок при вложенных группах. Если в шаблоне скобки внутри скобок, нумерация всё равно идёт по открывающей скобке слева направо, и легко сбиться, если структура сложная. В таких случаях полезно упрощать шаблон или разбивать его на несколько шагов.
И третья — забывать, что s/// без специального флага меняет только первое вхождение. Если ожидалось, что заменятся все повторения слова в тексте, а поменялось только одно — дело именно в этом, и решение уже совсем рядом, в следующем уроке.
Итоги
Оператор s/шаблон/замена/ ищет совпадение по шаблону и заменяет его прямо в переменной. Круглые скобки в шаблоне создают группы захвата, доступные потом как $1, $2, $3 — и их можно использовать не только для чтения найденного текста, но и прямо внутри замены, чтобы переставлять части строки местами. Это основа для любой более сложной обработки текста в Perl.