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

[ Perl ]

26 Jun 2012

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

Основной синтаксис

  • [ ] - символ, либо слайс, который может встретиться в поиске
  • **{ <число> }** - сколько раз встречается
  • **{<число>, <число>}** - промежуток сколько раз встречается. Если второго числа нет - то до бесконечности
  • * == {0, }
  • + == {1, }
  • ( ) - подстрока
  • . - почти все символы, кроме перевода строки
  • ** - экранирование следующего символа
  • \d - десятичные цифры == [0-9]
  • \D - всё кроме цифр
  • \w ** == [A-z]**
  • \W - всё кроме букв
  • ** ** - “ИЛИ”

Клини выяснил, что стандартные (математические) регулярные выражения не решают проблему парности строк.

  • (?{ }) - расширенное регулярное выражение
  • (? ) - группировка с захватом - ставит в соответствие переменным $1,$2.. те подстроки, которые удовлетворяют шаблону, заключённому в скобках
  • (?: ) - группировка без захвата

###Параметры:###

g - глобальность (используется чтобы итератор в цикле двигался по строке дальше)

i - игнорирование регистра

- игнорирование конца строки 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"; &nbsp;# всё таки выведет 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;