Вышеперечисленные метасимволы, квантификаторы, мнимые символы, специальные переменные -
это та часть статьи к которой вы будете обращаться чаще всего - поэтому я собрал все вместе.
А далее будем рассматривать более сложные решения задач, с пояснениями.
Начнем с создания регулярных выражений. А более точно со специальных переменных:
$string = "one two three four five";
$string =~ m/three/;
print $`; # результат: "one two "
print $'; # результат: " four five"
print $&; # результат: "three"
# теперь насчет массивов @+ и @-
print $-[0]; # результат: 8
print $+[0]; # результат: 13
# переменные $#-, $#+ указывают на длину @-, @+ соответственно
# с помощью функции substr() можно получить переменные $`, $', $&, например
$before_pat = substr($string,0,$-[0]); # аналог $`
$after_pat = substr($string,$+[0]); # аналог $'
$pattern = substr($string,$-[0],$+[0]-$-[0]); # аналог $&
Переменная $^R, пример:
$string = "some text";
$qwer =~ /(?{$var1=2.3;$var2=3.2})/;
print $^R;
Результат: 3.2
Переменная $+, пример:
$string = "some text";
$string =~ m/(\w+)\s+(\w+)/;
print $+;
Результат: text
Переменная $*, пример:
$string = "couple\nof\nlines\ngoes\nbellow...";
print $string =~ m/^lines/; # в этом случае пустая строка ""
$*=1; # после присвоения переменной $* истины, результат будет
print $string =~ m/^lines/; # - истина
Используем модификатор e для оператора s/.../.../:
$string = "words don't come easy";
$string =~ s/(\w+)/uc($1)/eg;
print $string;
Данный фрагмент кода "поднимает" регистр букв у всех слов из строки $string (глобально),
вот что получается:
WORDS DON'T COME EASY
Что такое альтернатива? Это вот что:
Данный фрагмент:
while(<>){
if(/^exit$/){last}
if(/^quit$/){last}
if(/^stop$/){last}
}
Можно заменить этим, с использованием альтернативы:
while(<>){
# это перебор с сравнением с текстом, т.е. если хотя бы один фрагмент из
# альтернативы совпадет с текстом, то возвращаемое значение примет истину.
# т.е. в данном случае если
пользователь введет в STDIN, exit или quit или же
stop,
# то мы завершим цикл
if(/^(quit|exit|stop)$/){
last;
}
}
Нужно проверить есть ли в строке слово ALPHA и слово BETA:
$string = "BETALPHA";
if(($string =~ /ALPHA/) and ($string =~ /BETA/)){
print "OK";
}
Или так:
if($string =~ /(?=.*ALPHA)(?=.*BETA)/){ # так не делать - пример для перекрывающихся совпадений
print "OK";
}
$string =~ /^(?:(?!PAT).)*$/
Выражение истинно если шаблон /PAT/ не совпадает (аналогично $string !~
/PAT/):
Далее насчет конструкций (?=шаблон) и т.д.:
В следующем примере ищется слово, за которым следует три восклицательных знака, но сам
пробел не включается в результат поиска:
$string = "One! Two!! Three!!! And some words next...";
$string =~ m/(\w+(?=!!!))/;
print $1;
Ответ: Three.
Вот тоже неплохой пример, взятый из книги Perl
Cookbook.
$string = "1234567890";
@nonlap = $string =~ /(\d\d\d)/g;
@yeslap = $string =~ /(?=(\d\d\d))/g;
print "Non-overlapping: @nonlap\n";
print "Overlapping: @yeslap\n";
Вот, что получается:
Non-overlapping: 123 456 789
Overlapping: 123 234 345 456 567 678 789 890
Идем дальше - совпадение с любым символом, т.е. точка (.), например:
$string = "secret password";
$string =~ s/./*/g;
print $string;
Хоть * - это квантификатор, но в данном случае предшествующего элемента нет поэтому
используется лексическое значение, и результат, такой:
**************
Но мнимый символ точка не совпадает с символом переноса строки, вот пример:
$string = "some text\nnew string";
$string =~ s/./*/g;
print $string;
Вот вывод программы:
*********
**********
Перенос строки остался, чтобы разрешить точке совпадать с переносом строки,
нужно добавить модификатор s, и все:
$string = "some text\nnew string";
$string =~ s/./*/gs;
print $string;
Результат:
********************
То, что нужно... Проверяем, в строке $string больше 80 символов или нет:
$string = "simple text";
$_ = $string;
if(/.{80,}/){
print "Length of text is OK";
}else{
print "Length of text isn't OK";
}
Теперь поговорим о квантификаторах.
$string = "It is some text!!!!!!!!!!!!!!!!!";
$string =~ s/!+/!/;
print $string;
В этом случае вывод будет таков:
It is some text!
Квантификатор + означает одно или более совпадений, но т.к. квантификаторы количества изначально
являются "жадными" (о жадности квантификаторов ниже), то в данном случае квантификатор + заменит
самую длинную последовательность восклицательных знаков, а вот если поставить этот
квантификатор - *, то в первом случае он отработает также, но если строку заменить на эту:
$string = "It is some text";
Тогда результат будет следующим:
!It is some text
Удивлены? Да, именно такой результат и будет (не забыли? квантификатор * означает ноль или более
совпадений), т.к. в данном случае нет восклицательных знаков, то он удовлетворяется нулем.
Теперь посмотрим если нужно определенное количество символов, например:
$string = "It is some text!!!!!!!!?!!!!!!!!";
$string =~ s/!{8}//;
print $string;
Здесь мы удаляем ровно 8 восклицательных знаков, поэтому результат будет такой:
It is some text?!!!!!!!!
Если мы добавим модификатор g, то и последние 8 восклицательных знаков тоже исчезнут, а
вот если сделать 9 восклицательных знаков, тогда ничего не будет заменено...
Теперь о "жадности" квантификаторов, как говорилось выше, квантификатор заменит самую
длинную серию - это и есть жадность. Разберем такой пример, вы хотите заменить "That is" на "That's":
# вероятно вы сделате так
$string = "That is reality, isn't it?";
$string =~ s/.*is/That's/;
print $string;
Результат будет такой:
That'sn't it?
Т.к. "жадность" квантификаторов проявляется слева направо, будет
выбрана максимальная серия слева направо. Это исправить легко - просто добавляем знак вопроса "?":
$string =~ s/.*?is/That's/;
И теперь результат будет тот, что нужно:
That's reality, isn't it?
Вопросительный знак обозначает ноль или одно совпадение, поэтому как только найдено первое
совпадение оно сразу заменяется, и все. Вот список минимальных квантификаторов: +?, *?, ??, {}?.
Дальше несколько примеров с квантификаторами.
Удаляем начальные пропуски
$string = " Some text";
$string =~ s/^\s+//;
Удаляем конечные пропуски
$string = "Some text ";
$string =~ s/\s+$//;
А теперь классы и группы. Класс символов - это символ, или список символов заключенные в квадратные скобки. Любой
символ из квадратных скобок сопоставляется со строкой для сравнения, например:
$string = "Berry";
if ($string =~ /[br]/){
print "B and R";
}
В данном случае оператор m/.../ используется в скалярном контексте, поэтому в случае
совпадения шаблона возвращает истину, иначе пустую строчку. Знак дефис (-) имеет особый
смысл для класса символов - диапазон символов (в начале указывается начальный символ,
потом конечный), например:
$string = "some Text";
if($string =~ /[A-Z]/){
print "Uppercase here...";
}
Или вот другой пример:
# если есть буквы то возвращает истину
$string = "some text";
if($string =~ /[A-Za-z]/){
print "Letters here...";
}
Здесь диапазон от A до Z, заглавных букв, т.е. если в строчке есть хотя бы одна заглавная
буква, то оператор m/.../ возвращает истину. А если перед открывающей квадратной скобкой
поставить символ ^, тогда смысл меняется на противоположный, т.е. символ сравнивается,
с любым не входящим в этот класс.
(Продолжение следует)