Студопедия

КАТЕГОРИИ:

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

Работа команды m/.../ в режиме глобального поиска




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

 

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

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

print "Single: [", join(", ", array),"].\n";

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

print "Global: [", join(", ", array),"].\n";

Single: [-one, one].

Global: [-one, one, -two, two, -three, three].

Если же в шаблоне нет групп круглых скобок, то оператор поиска возвращает список всех найденных прототипов шаблона, то есть ведет себя так, как если бы весь шаблон был заключен в круглые скобки:

 

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

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

print "Result: (", join(", ", @array), ").\n";

Result: (one, two, three).

В случае неудачного поиска, как и в предыдущих вариантах, возвращается пустой список. В скалярном контексте и с модификатором g комaндa m/.../ведет себя совершенно особым образом. Специальная переменная $_ или переменная, стоящая слева от оператора =~ или !~, при поиске с модификатором gполучает дополнительные свойства - в нее записывается последнее состояние. При каждом последующем обращении к данному фрагменту кода поиск будет продолжаться с того места, на котором он остановился в последний раз. Например, следующая команда подсчитывает количество букв х в заданной строке текста:

 

$text = "Here is texxxxxt.";

$counter = O;

while ($text =~ m/x/g){

print "Found another x.\n";

$conter++;

print "Total amount = $counter.\n";

Found another х.

Found another х.

Found another x.

Found another x.

Found another x.

Total amount = 5.

Состoяние (точнее, позиция) поиска сохраняется даже в случае перехода к следующему оператору поиска, имеющему модификатор g. Неудачный поиск сбрасывает значение в исходное состояние, если только для команды m/.../ не указан модификатор с (то есть команда должна иметь вид m/.../gc). Изменение текстового буфера, для которого выполняется поиск, также сбрасывает позицию поиска в исходное состояние. В следующем примере из текстовой строки последовательно извлекаются и выводятся пары имя/значение до тех пор, пока строка не закончится:

 

$text = "X=5; z117e=3.14l6; temp=lQ24;";

$docycle = 1; $counter = 0;

while ($docycle) {

undef $name; undef $value;

if ($text =~ m/(\w+)\s*=\s*/g) {$name = $1;}

if ($text =~ m/([\d\.\*\-]*)\s*;/g) {$value = $1;}

if (defined($name) and defined($value)) {

print "Name=$name, Value=$value.\n";

$counter++,

}else{

$docycle = 0;

}

}

print "I have found $conter values.\n";

Name=X, Value=5.

Name=z117e, Value=3.1416.

Name=temp, Value=1024.

I have found 3 values.

 

Позиция, на которой остановился поиск, может быть прочитана и даже переустановлена с помощью встроенной функции perl pos. В шаблоне на текущую позицию поиска можно ссылаться с помощью метасимвола \G. В следующем примере из строки последовательно извлекаются буквы p, o и q и выводится текущая позиция поиска:

 

$index = 0;

$_ = "ppooqppqq";

while ($index++ < 2) {

print "1: '";

print $1 while /(o)/gc; print "', pos=", pos, "\n";

print "2: '";

print $1 if /\G(q)/gc; print "', pos=";' pos, "\n";

print "3: '";

print while /(p)/gc; print "', pos=",pos, "\n";

}

1: 'oo', pos=4;

2: 'q', pos=7;

3: 'pp', pos=4;

1: '', pos=7;

2: 'q', pos=8;

3: '', pos=8;

В документации perl приводится основанный на этом механизме интересный пример последовательного лексического разбора текста. В нем каждая последующая команда поиска очередной лексической единицы начинает выполнятьсяс того места, где завершила свою работу предыдущая (страница руководства perlop, раздел "Regexp Quote-Uke Operators", описание команды m/PATTERN/).

 

Замена строк с помощью команды tr/.../.../

Кроме команд m/.../ и s/.../.../строки можно обрабатывать с помощью команды tr/.../.../(она же - команда у/.../.../):

 

tr/список1/список2/модификаторы;

у/список1/список2/модификаторы;

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

 

$text = "My name is Tim.";

$text =~ tr/i/o/; print $text;

MynameisTom.

В качестве списков используются идущие друг за другом символы, не разделяемые запятыми (то есть это скорее строки, чем списки). В отличие от шаблонов команд m/.../и s/.../.../, аргументы команды tr/.../.../ не интерполируются (то есть подстановки значений вместо имен переменных не происходит), хотя escape-последовательности, указанные внутри аргументов, обрабатываются правильно. Подобно m/.../ и s/.../.../, команда tr/.../.../ пo умолчанию работает с переменной $_:

 

while (<>){

tr/iI/jJ/;

print;

В качестве списков можно указывать диапазоны символов - как, например, в следующем фрагменте кода, заменяющем строчные буквы на заглавные:

 

$text = "Here is the text.";

$text =~ tr/a-z/A-Z/;

print $text;

HERE IS THE TEXT.

Как и в случае m/.../ u s/.../.../, команда tr/.../.../ не требует использовать именно знаки косой черты в качестве ограничителей. Можно использовать практически любой символ, отличный от "пробельных", букв и цифр, а также парные скобочные конструкции.

Команда tr/.../.../ возвращает число успешных замен. В частности, если не было сделано никаких замен, она возвращает число ноль. Это позволяет, например, подсчитать с помощью команды tr/.../.../ количество вхождений буквы х в строку $text, не меняя содержимого этой переменной:

 

$text = "Here is the text.";

$xcount = ($text =~tr/x/x/);

print $xcount;

1

 

Еслиукомандыtr/.../.../ нет модификаторов (см. далее раздел "Модификаторы команды tr/.../.../"), то ее аргументы при обычных условиях должны быть одинаковой длины. Если второй аргумент длиннее первого, то он усекается до длины первого аргумента - так, команда tr/abc/0-9/ эквивалентна команде tr/abc/012/. Если первый аргумент длиннее второго и второй не пуст, то для второго аргумента необходимое число раз повторяется его последний символ - так, команда tr/O-9/abc/ эквивалентна команде tr/0123456789/abcccccccc/. Если же второй, аргумент пуст, то команда tr/.../.../ подставляет вместо него первый аргумент.

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

 

$text = "Pi=3.1415926536, е=2.7182";

$digit_counter=($text =~ tr/0-9//);

print $digit_counter;

16

Команда tr/.../.../ работает без рекурсии, просто последовательно заменяет символы входного текста. Например, для замены заглавных букв на строчные, и наоборот, достаточно выполнить команду:

 

$text = "MS Windows 95/98/NT";

$text =" tr/A-Za-z/a-zA-Z/;

print $text;

Ms WINDOWS 95/98/nt

 

Если в списке, указанном в качестве первого аргумента, есть повторяющиеся символы, то для замены используется первое вхождение символа:

 

$text = "Billy Gates";

$text =~ tr/ttt/mvd/;

print $text;

Billy Games

 

Модификаторыкоманды tr/.../.../

Команда tr/.../.../допускает использование следующих модификаторов:

  • d- удаляет непарные символы, не выравнивая аргументы по длине.
  • с - в качестве первого аргумента использует полный список из 256 символов за вычетом указанных в списке символов.
  • s - удаляет образовавшиеся в результате замены повторяющиеся символы.

Если указан модификатор d, a первый аргумент команды длиннее второго, то все символы из первого списка, не имеющие соответствия со вторым списком, удаляются из обрабатываемого текста. Пример: удаляем строчные латинские буквы и заменяем пробелы на слэши:

 

$text = "Here is the text.";

$text =~ tr[ a-z][/]d;

print $text;

H///.

 

Наличие модификатора d- единственный случай, когда первый и второй аргументы не выравниваются друг относительно друга, В остальных вариантах второй аргумент либо усекается, либо последний символ в нем повторяется до тех пор, пока аргументы не сравняются, либо, если второй аргумент пуст, вместо второго аргумента берется копия первого.

Если указан модификатор с, то в качестве первого аргумента рассматриваются все символы, кроме указанных. Например, заменим на звездочки все символы, кроме строчных латинских букв:

 

$text = "Here is the text,";

$text =' tr/a-z/*/c;

print $text;

*ere*is*the*text*

Если указан модификатор s, то в случае если замещаемые символы образуют цепочки из одинаковых символов, они сокращаются до одного. Например, заменим слова, состоящие из латинских букв, на однократные символы косой черты:

 

$text = "Here is the text.";

$text ="tr(A-Za-z)(/)s;

print $text;

/ / / /.

Без модификатора s результат был бы другим:

 

$text = "Here is the text.";

$text =' tr(A-Za-z)(/);

print $text;

//// // /// ////.

Примеры


1. Заменить множественные пробелы и нетекстовые символы на одиночные пробелы:

$text = "Here is the text."

$text =~ tr[\000-\040\177\377][\040]s;

print $text;


Here is the text.

2. Сократить удвоенные, утроенные и т.д. буквы;

$text = "Here is the texxxxxxt.";

$text =~ tr/a-zA-Z/s;

print $text;

Here is the text.

 

3. Пересчитать количество небуквенных символов:

$xcount=($text =~ tr/A-Za-z//c);

 

4. Обнулить восьмой бит символов, удалить нетекстовые символы:

$text =- tr{\200-\377}{\000-\l77};

$text =~ tr[\000-\037\177][]d;

 

5. Заменить нетекстовые и 8-битные символы на одиночный пробел:

$text =~ tr/\021-\176/ /cs;

 

Поиск отдельных слов

Чтобы выделить слово, можно использовать метасимвол \S соответствующий символам, отличным от "пробельных":

 

$text = "Now is the time.";

$text =- /(\S+)/;

print $1;

Now

Однако метасимвол \S соответствует также и символам, обычно не используемым для идентификаторов. Чтобы отобрать слова, составленные из латинских букв, цифр и символов подчеркивания, нужно использовать метасимвол \w:

 

$text = "Now is the time.";

$text =~ /(\w+)/;

print $1;

Now

Если требуется включить в поиск только латинские буквы, надо использовать класс символов:

 

$text = "Now is the time.";

$text =~ /([A-Za-z]+)/;

print $1;

Now

Более безопасный метод состоит в том, чтобы включить в шаблон мнимые символы границы слова:

 

$text = "How is the time.";

$text=~/\b([A-Za-z]+)\b/;

print $1;

Now

 

Привязка к началу строки

Началу строки соответствует метасимвол (мнимый символ) ^. Чтобы шаблон к началу строки, надо задать этот символ в начале регулярного выражения. Например, вот так можно проверить, что текст не начинается с точки:

 

$line = ".Hello!";

if($line=~m/^\./){

print "Shouldn't start a sentence with a period!\n";

}

Shouldn't start a sentence with a period!

Чтобы точка, указанная в шаблоне, не интерпретировалась как метасимвол перед ней пришлось поставить обратную косую черту.

 

Привязка к концу строки

Чтобы привязать шаблон к концу строки, используется метасимвол (мнимый символ) $. В нашем примере мы используем привязку шаблона к началу и к концу строки, чтобы убедиться, что пользователь ввел только слово "exit":

 

while(<>){

if(m/"exlt$/) {exit;}

}

Поиск чисел

 

Для проверки того, действительно ли пользователь ввел число, можно использовать метасимволы \d и \D. Метасимвол \D соответствует любому символу, кроме цифр. Например, следующий код проверяет, действительно ли введенный текст представляет собой целое значение без знака и паразитных пробелов:

 

$test = "Hello!";

if($text =~ /\D/){

print "It is not a number.\n";

}

It is not a number.

To же самое можно проделать, использовав метасимвол \d:

 

$text = "333";

if($text =~ /^\d+$/){

print "It is a number.\n";

}

It is a number.

Вы можете потребовать, чтобы число соответствовало привычному формату. То есть число может содержать десятичную точку, перед которой стоит по крайней мере одна цифра и, возможно, какие-то цифры после нее:

 

$text= "3,1415926";

if($text =~ /^(\d+\.\d*|\d+)$/){

print "It is a number.\n";

}

It is a number.

 

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

 

$text = "-2.7182";

if ($text =~ /^([+-]*\d+)(\.\d*|)$/) {

print "It is a number.\n";

 

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

$text = "+0.142857142857142857";

if ($text =~ /^(+|-|)\d+(\.\d*\)$/) {

print "It is a number.\n";

}

It is a number.

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

$text = "1AO";

unless (ftext =~ m/^[a-fA-F\d]+$/) {

print "It is not a hex number, \n";

}

 

Проверка идентификаторов

 

С помощью метасимвола \w можно проверить, состоит ли текст только из букв, цифр и символов подчеркивания (это те символы, которые perl называет словесными (word characters)):

 

$text="abc";

if($text=~/^\w+$/){

print "Only word characters found. \n";

}










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

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