Регулярные выражения Perl
Основной синтаксис
- [ ] - символ, либо слайс, который может встретиться в поиске
- **{ <число> }** - сколько раз встречаетсячисло>
- **{<число>, <число>}** - промежуток сколько раз встречается. Если второго числа нет - то до бесконечностичисло>число>
- * == {0, }
- + == {1, }
- ( ) - подстрока
- . - почти все символы, кроме перевода строки
- ** - экранирование следующего символа
- \d - десятичные цифры == [0-9]
- \D - всё кроме цифр
- \w ** == [A-z]**
- \W - всё кроме букв
-
** ** - “ИЛИ”
Клини выяснил, что стандартные (математические) регулярные выражения не решают проблему парности строк.
- (?{ }) - расширенное регулярное выражение
- (? ) - группировка с захватом - ставит в соответствие переменным $1,$2.. те подстроки, которые удовлетворяют шаблону, заключённому в скобках
- (?: ) - группировка без захвата
###Параметры:###
g - глобальность (используется чтобы итератор в цикле двигался по строке дальше)
i - игнорирование регистра
m - игнорирование конца строки Match ~m/A(B*)/ - ищет подстроку, где идет А, потом произвольное количество символов B
while ($r="CDABABB"=~m/(?:A(B*))/g) {print "$r $1 \n"; }
Вывод:
1 B
1 BB
while ($r="CDABABB"=~m/(A+|B+)/g) {print "$r $1 \n"; }
Вывод:
1 A
1 B
1 A
1 BB
while ($r="CDABABB"=~m/(A*|B*)/g) {print " $r $1 \n"; }
Вывод:
1
1
1 A
1
1 B
1 A
1
1 BB
1
@r="CDABABB"=~m/(A+|B+)/g; print " @r \n";
Вывод:
A B A BB
S
s/ / /; Замена найденного тем, что справа.
y
**y/ / /; заменяет первое найденное на первое справа, второе - на второе. и.т.п.
tr
**tr/ / /; тоже замены
##Задачи##
Задача о простейших совпадениях
Пусть есть файл Ф И О Ф И О
(6 колонок)
Нужно выдать всех многожёнцев.
#!/usr/bin/perl -w
$SRC_FN = "fiofio.txt";
open RFD, "<$SRC_FN" or die "Невозможно открыть файл $SRC_FN: $!";
while (<RFD>) {@s = split ' ',$_;
if (@s!=6)
{ print STDERR "Invalid line $.\n";
next;}
$p1=join ' ',@s[0..2];
$p2=join ' ',@s[3..5];
$h{$p1}{$p2} = $h{$p2}{$p1}=1;
}
close RFD or die "Невозможно закрыть $SRC_FN:$!";
{local $\=$/;
print grep { (keys %{$h{$_}})>1 } keys %h;}
Поиск парных символов
Есть текст $_; программа д.б. написана в / /x; (регвыр) Должна выдавать если ровно два одинаковых символа, то выдавать количество всех пар. Если пар нет - выдать 0 Проблема в том, что во-первых, символ произвольный, во-вторых, строка ааа - работает, а это плохо. Выражение /(a|b)$1/ то подставится то значение, которое было до него. А чтобы получить то, что хотим, надо подставить \1 вместо $1 Doubles.pl
Нахождение нужного положения в строке
Константы можно писать с подчёркиванием.
$a= 1_000_000;
print "$a\n"; # всё таки выведет 1000000
Поэтому хочется написать процедуру, которая будет вставлять подчёркивание
Поиск конкретных последовательностей символов
Для ознакомления с возможностями регулярных выражений, таких как:
- Не равно
- Равно
- Заглядывание вправо или влево от найденного,
Напишем программу для выделения IP адресов IpParser
Вложенные регулярки
(??{ }) Блок кода рассматривается как регулярное выражение. То есть мы можем написать здесь reverse $1 и работать с этим легко.
Вложенные скобки
#!/usr/bin/perl -w
$_="(())";
$ptrn=qr/
\(
(?:
(?>[^()]+)
|
(??{$ptrn})
)*
\)
/x;
$_=~/^(?>[^()]*)$ptrn(?>[^()]*)$/ or print "Error\n";
Произвольная функция
Есть текст на С. У какой то функции перед последней скобкой вставить какой-то параметр, например: some_func(x,y,z) -> some_func(x,y,z ,NULL)
#!/usr/bin/perl -w
$_="some_func(x(y),z)";
$ptrn=qr/
\(
(?:
(?>[^()]+)
|
(??{$ptrn})
)*
\)
/x;
$_=~s/(some_func\s*$ptrn)/$t=$1; substr($t,-1)=", NULL)"; $t/gxmse;
print;