Отправляет email-рассылки с помощью сервиса Sendsay
  Все выпуски  

CGI-программирование с самого начала


Информационный Канал Subscribe.Ru

Уважаемые подписчики!

Сегодня мы заканчиваем тему регулярных выражений. Нам осталось только прояснить один момент практического использования регулярных выражений, а именно работу с неоднозначными соответствиями и управление "аппетитом" модификаторов количества. Итак...

Использование метасимвола '.' (продолжение)

Еще одним "подводным камнем" в использовании модификаторов (в частности, "*" и "+") является, так сказать, возможная многовариантность (неоднозначность) соответствия.

Сразу поясню примером.

Допустим, нам надо вырезать из строки все фрагменты в скобках:


#Исходный текст
 $txt="текст1 (скобки1) текст2";
 $txt=~s/\(.*\)//g;
 print $txt;

Попутно обратите внимание, что в шаблоне мы перед скобками поставили символ обратной косой черты. Это нужно для того, чтобы дать Perl понять, что мы имеем в виду именно символы скобок, поскольку скобки являются "специальными символами" в шаблонах. В качестве замены мы используем просто пустую строку.

Результат такой, как мы и ожидали:

текст1 текст2

А теперь попробуем обработать строку, в которой не одни скобки, а несколько:



 $txt="текст1 (скобки1) текст2 (скобки2) текст3";
 $txt=~s/\(.*\)//g;
 print $txt;

Логично было бы ожидать следующего результата:

текст1 текст2 текст3

Но вместо этого мы с большим удивлением получаем:

текст1 текст3 !

Куде же делся 'текст2'? Что же произошло? Что мы сделали не так?

Как ни странно, мы все сделали почти так, как надо. И Perl все сделал... вполне в соответствии тому, что мы ему задали. Просто здесь имеют место неоднозначные соответствия, т.к. шаблону "\(.*\)" соответствует как подстроки "(скобки1)" и "(скобки2)" так и подстрока "(скобки1) текст2 (скобки2)"!

По умолчанию модификаторы количества (quantifiers) в шаблонах являются "жадными", т.е. "забирают под себя" столько символов строки, сколько можно (что и имело место в нашем случае). Однако есть возможность их "перевоспитать" - изменить их поведение таким образом, чтобы они "забирали под себя" не максимально, а минимально возможное количество символов. Для этого надо после модификатора в шаблоне поставить вопросительный знак:

 $txt="текст1 (скобки1) текст2 (скобки2) текст3";
 $txt=~s/\(.*?\)//g;
 print $txt;

Пробуем - и получаем то, что ожидали:

'текст1 текст2 текст3'

Простейший способ увидеть действие модификатора "?" - использовать поиск по шаблону ".*" или ".+"; в этом случае неоднозначные соответствия будут иметь место применительно к любой строке.

Попробуем такой фрагмент:

 $a="ABCD";
 @f=$a=~/.+/g;
 foreach $itm(@f) {print "$itm\n"};

Этот код ищет в строке соответствия шаблону и затем выводит их на экран в столбик.

Как мы и ожидали, соответствие в данном случае будет одно - все содержимое строки, т.к. "жадный" модификатор '+' "заберет под себя" максимально возможное количество символов.

А теперь попробуем поставить после "+" символ "?" и посмотреть на результат в этом случае. Поскольку модификатор "+" в этом случае будет забирать под себя минимальное количество символов, то в качестве соответствий мы получим отдельные символы строки.

Интересный результат получится, если в вышеуказанном примере вместо шаблона '.+' использовать шаблон '.*', допускающий соответствие "пустая строка" (модификатор '+', как мы помним, обозначает "1 символ и более", а '*' - "0 символов и более"). В этом случае со знаком '?' мы получим не 4, а 7 (!) соответствий! Ими будут как символы строки, так и... промежутки между ними (пустые строки)! Действительно, именно такое минимальное количество символов может "забрать под себя" модификатор '*'...

Переменная "по умолчанию", или еще одна песня практичности Perl

А сейчас я хочу рассказать об одной приятной особенности языка Perl.

Очень часто в процессе написания программы программисту бывает нужно ввести временную рабочую переменную.

Скажем, в вышерассмотренном примере так можно назвать переменную $itm, которая нужна только для передачи значений внутрь цикла, и после отработки цикла, образно говоря, про нее и не вспомнят. :-)

А поскольку считается некрасивым (хотя, в большинстве случаев, допустимым практически) использовать одну переменную в разных местах программы для разных целей, то для каждой такой переменной приходится придумывать свое имя.

Поскольку язык Perl создавался и развивался исходя из практических потребностей программистов, то он имеет одну особенность, позволяющую несколько облегчить использование "рабочих" переменных, делая при этом код не менее, а даже более красивый.

Эта особенность заключается в существовании "переменной по умолчанию", которая подразумевается во многих функциях при отсутствии явно заданного аргумента или другого параметра. Имя этой переменной - $_

С использованием переменной $_ вышеприведенный фрагмент программного кода может выглядеть так:

 $a="ABCD";
 @f=$a=~/.+/g;
 foreach (@f) {print; print "\n"};

В данном примере оператор foreach будет присваивать значения элементов массива @f переменной $_, поскольку ему имя переменной явно не указано, а первая функция print (без аргументов) также будет принимать эту переменную в качестве аргумента.

Конечно же, можно задавать переменную $_ и явно - например, если в функции используется несколько аргументов или значение $_ должно быть использовано в выражении.


На сегодня все. До следующих выпусков!

Обсудить рассылку на форуме


Успехов!
Андрей
angel07@inbox.ru

Subscribe.Ru
Поддержка подписчиков
Другие рассылки этой тематики
Другие рассылки этого автора
Подписан адрес:
Код этой рассылки: inet.webbuild.perlcgi
Архив рассылки
Отписаться
Вспомнить пароль

В избранное