Студопедия

КАТЕГОРИИ:

АвтоАвтоматизацияАрхитектураАстрономияАудитБиологияБухгалтерияВоенное делоГенетикаГеографияГеологияГосударствоДомЖурналистика и СМИИзобретательствоИностранные языкиИнформатикаИскусствоИсторияКомпьютерыКулинарияКультураЛексикологияЛитератураЛогикаМаркетингМатематикаМашиностроениеМедицинаМенеджментМеталлы и СваркаМеханикаМузыкаНаселениеОбразованиеОхрана безопасности жизниОхрана ТрудаПедагогикаПолитикаПравоПриборостроениеПрограммированиеПроизводствоПромышленностьПсихологияРадиоРегилияСвязьСоциологияСпортСтандартизацияСтроительствоТехнологииТорговляТуризмФизикаФизиологияФилософияФинансыХимияХозяйствоЦеннообразованиеЧерчениеЭкологияЭконометрикаЭкономикаЭлектроникаЮриспунденкция

Особенности работы команд m/.../ и s/.../.../.




До сих пор мы рассматривали регулярные выражения, используемые в качестве шаблонов для команд m/.../и s/.../.../,и не особо интересовались, как работают эти команды. Настало время восполнить пробелы.

Команда m/.../ищет текст по заданному шаблону. Ее работа и возвращаемое значение сильно зависят от того, в скалярном или списковом контексте она используется и имеется ли модификатор g (глобальный поиск).

Команда s/.../.../ищет прототип, соответствующий шаблону, и, если поиск оказывается успешным, заменяет его на новый текст. Без модификатора замена производится только для первого найденного совпадения, с модификатором g выполняются замены для всех, совпадений во входном тексте. Команда возвращает в качестве результата число успешных замен или пустую строку (условие ложь false), если ни одной замены сделано не было. В качестве анализируемого текста используется $_ (режим по умолчанию) или выражение, присоединенное к шаблону с помощью оператора =~ или !~. В случае поиска (команда m/.../) конструкция, расположенная слева от операторов =~ или !~, может и не быть переменной. В случае замены (команда s/.../.../) в левой части должна стоять скалярная переменная, или элемент массива, или элемент хэша, или же команда присвоения одному из указанных объектов.

Вместо косой черты в качестве ограничителя для аргументов команд m/.../ и s/.../.../ можно использовать любой символ, за исключением "пробельного символа", буквы или цифры. Например, в этом качестве можно использовать символ комментария, который будет работать как ограничитель:

 

$text="ABC-abc";

$text =~ s#B#xxx#ig;

print $text;

AxxxC-axxxc

В качестве ограничителей не стоит использовать вопросительный знак и апостроф (одинарную кавычку) - шаблоны, с такими ограничителями обрабатываются специальным образом. Если команда m/.../ использует символ косой черты в качестве разделителя, то букву m можно опустить:

 

while (defined($text = <>))

{ if ($text =~/^exit$/i) {exit;} }

Если в качестве ограничителя для команды m/.../ используется вопросительный знак, то букву m также можно опустить. Однако шаблоны, ограниченные символом ?, в случае поиска работают особым образом (независимо от наличия или отсутствия начальной m). А именно, они ведут себя как триггеры, которые срабатывают один раз и потом выдают состояние ложь (false), пока их не взведут снова, вызвав функцию reset (она очищает статус блокировки сразу всех конструкций ?...?, локальных для данного пакета). Например, следующий фрагмент сценария проверяет, есть ли в файле пустые строки:

 

while (<>)

if (?^$?) {print ."There is an empty line nere.\n";} continue {

Reset if eof; #очистить для следующего файла

}

Диагностическое сообщение будет напечатано только один раз, даже если в файле присутствует несколько пустых строк. Команда поиска с вопросительным знаком относится к подозрительным командам, а потому может не войти в новые версии perl. В качестве ограничителей можно также использовать различные (парные) конструкции скобок:

 

while (<>){

if(m/^quit$/i){exit;}

if(m(^stop$)i){exit;}

if(m[^end$]i) {exit;}

if(m{^bye$}i) {exit;}

if (!1)<^ехit$>i) {exit;}

}

 

В случае команды s/.../.../и использования скобок как ограничителей для первого аргумента, ограничители второго аргумента могут выбираться независимо:

 

$text =~ "Perl is wonderful";

$text =~ s/is/is very/;

$text =~ s[wonderful]{beautiful};

$text =~ s(\.)/!/;

print $text;

Perl is very beautiful!

Предварительная обработка регулярных выражений

Аргументами команд m/.../и s/.../.../являются регулярные выражения, которые перед началом работы интерполируются подобно строкам, заключенным в двойные кавычки В отличие от текстовых строк, для шаблона не выполняется интерполяция имен типа $), $| и одиночного $ - perl считает, что такие конструкции соответствуют метасимволу конца строки, а не специальной переменной. Если же в результате интерполяции шаблон поиска оказался пустой строкой, perl использует последний шаблон, который применялся им для поиска или замены.

Если вы не хотите, чтобы perl выполнял интерполяцию регулярного выражения, в качестве ограничителя надо использовать апостроф (одиночную кавычку), тогда шаблон будет вести себя, как текстовая строка, заключенная в апострофы. Однако, например, в случае команды замены s/.../.../ с модификатором е или ее (их работа описывается чуть дальше) для второго аргумента будет выполняться интерполяция даже в том случае, если он заключен в апострофы.

Если вы уверены, что при любом обращениик команде поиска или замены шаблон остается неизменным (например, несмотря на интерполяцию, скалярные переменные внутри шаблона не будут менять своего значения), то можно задать модификатор о. Тогда perl компилирует шаблон в свое внутреннее представление только при первой встрече с данной командой поиска или замены. При остальных обращениях к команде будет использовать откомпилированное значение. Однако, если внезапно изменить значение переменных, задействованных в шаблоне, perl этого даже не заметит.

Команда замены s/.../.../ использует регулярное выражение, указанное в качестве второго аргумента, для замены текста. Поскольку оно обрабатывается (интерполируется) после того, как выполнена очередная операция поиска, в нем можно, в частности, использовать временные переменные, созданные на этапе поиска. В следующем примере мы последовательно заменим местами пары слов, заданных во входном тексте, оставив между ними по одному пробелу:

 

$text = "One Two Three Four Five Six";

$text =- s/(\w+)\s*(\w+)/$2$1/g;   

Two One Four Three Six Five

Однако perl допускает и более сложные способы определения заменяющего текста. Так, если для команды s/.../.../ указать модификатор е, то в качестве второго аргумента надо указать код, который необходимо выполнить (например, вызвать функцию). Полученное выражение будет использованокак текст для подстановки. При этом после вычисления текстового значения, но перед его подстановкой будет выполнен процесс интерполяции, аналогичный процессу интерполяции текстовых строк, заключенных в двойные кавычки. Еще более сложная схема реализуется, если задан модификатор ее. В этом случае второй аргумент команды s/.../.../ - это строковое выражение, которое сперва надо вычислить (то есть интерполировать), затем выполнить в качестве кода (вызвав встроенную функцию eval) и только после второй интерполяции полученный результат подставляется вместо найденного текста.

Работа команды m/.../ в режиме однократного поиска В скалярном контексте и без модификатора g команда m/.../ возвращает логическое значение - целое число 1 (истина (true)), если поиск оказался успешным, и пустую строку "" (ложь (false)), если нужный фрагмент текста найти не удалось. Если внутри шаблона имеются группы элементов, заключенные в круглые скобки, то после операции поиска создаются нумерованные переменные $1, $2, ..., в которых содержится текст, соответствующий круглым скобкам. В частности, если весь шаблон заключить в круглые скобки, то в случае успешного поиска переменная $1 будет содержать текст, соотнесенный с шаблоном. После успешного поиска можно также использовать специальные переменные $&, $', $' и $+

 

$text = "---one---two---three---";

$scalar = ($text =' m/(\w+)/);

print "Result: $scalar ($1).";

Result: 1 (one).

Если вы используете команду m/.../ в списковом контексте, то возвращаемое значение сильно зависит от того, есть ли группы из круглых скобок в вашем шаблоне. Если они есть (то есть если создаются нумерованные переменные), то после успешного поиска в качестве результата будет получен список, составленный из нумерованных переменных ($1, $2,...):

 

$text = "---one, two, three---";

 array = ($text ='m/(\w+),\s+(\w+),\s+(\w+)/);

print join "=", array;

one=two=three.

В отличие от ранних версий, perl 5 присваивает значения нумерованным переменным, даже если команда поиска работает в списковом контексте:

 

$text = "---one, two, three--- ";

($Fa, $Fb, $Fc) = ($text=-m/(\w+),\s+(\w+),\s+(\w+)/);

print "/$Fa/$Fb/$Fc/\n";

print "$1=$2=$3.\n";

/one/two/three/

one=two::three.

Если же в шаблоне нет групп, выделенных круглыми скобками, то в случае успешного поиска возвращается список, состоящий из одного элемента - числа 1. При неудачном поиске независимо от того, были ли в шаблоне круглые скобки, возвращается пустой список:

 

$text = "---one, two, three--- ";

@array = ($text=~ m/z\w+/);

print "Result: /", @array, "/\n";

print "Size: ", $#array+1, ".\n";

Result://

Size: 0.

 

Обратите внимание на разницу между пустым и неопределенным списками.

 










Последнее изменение этой страницы: 2018-04-12; просмотров: 396.

stydopedya.ru не претендует на авторское право материалов, которые вылажены, но предоставляет бесплатный доступ к ним. В случае нарушения авторского права или персональных данных напишите сюда...