Студопедия

КАТЕГОРИИ:

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

Как удалить ведущие и завершающие пробелы




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

 

$text = "     Now is the time.";

$text =~ s/^\s+//;

print $texts;

Nowisthetime.

Чтобы отсечь "хвостовые" пробелы, годится команда:

$text = "Now is the time.     ";

$text =~ s/\s+$//;

print $texts;

Nowisthetime.

 

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

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

 

$text="<a>blah-blah</a>";

if($text=~m!<([a|b])>(.*?)/\1!ig){

print "$2\n";

}

 

найдет все слова, стоящие между тегами <a></a> и <b></b>.

В регулярных выражениях присутствует своя семантика: быстрота, торопливость и возврат. Если квантификатор * совпадает во многих случаях, то в результате будет выведен наибольший по длине результат. Это жадность. Быстрота: поиск старается найти как можно быстрее. "Text"=~/m*/, по смыслу символов m нет, но в результате будет возвращено значение 0. Т.е. формально 0 и более символов.

 

$test="aaooee ooaao";

$test=~s/o*/e/;

print $test;

Eaaooee ooaao

 

потому что 1 элемент строки - 0 и более символов.

Если добавить квантификатор g, то результат будет таким:eaeaeeeeee eeaeaee, т.к строка содержит 13 мест, где может встречается o, в том числе и пустых.

Модификаторы:

  • /i игнорировать регистр;
  • /x игнорировать пропуски в шаблоне и разрешить комментарии;
  • /g модификатор разрешающий выполнение поиска/замены везде, где это возможно;
  • /gc не сбрасывается позиция при неудачном поиске;
  • /s разрешается совпадение. с \n, игнорируется $*;
  • /m разрешить совпадение ^ и $ для начала и конца строки во внутренних переводах строк;
  • /o однократная компиляция;
  • /e правая часть s/// представляет собой выполняемый код;
  • /ee правая часть s/// выполняется, после чего возвращаемое значение интерпретируется снова.

при вызове use locаleучитываются локальные настройки. Модификатор /g может заполнить массив значений @nums = m/(\d+)/g;но это сработает для ненакладывающихся совпадений. Чтобы поймать совпадения нужно воспользоваться оператором ?=... Если ширина = 0, то механизм поиска остался на прежнем месте. Найденные данные остаются внутри скобок. Если есть модификатор /g, то текущая позиция остается прежней, но происходит перемещение на один символ вперед.

 

$numbers="123456789";

@one=$numbers=~/(\d\d\d)/g;

@two=$numbers=~/(?=(\d\d\d))/g;

print "@one \n"; print "@two \n";

Модификаторы m и s нужны для поиска последовательностей символов, содержащих перевод строки. При s точка совпадает с \n и игнорируется $*. m делает совпадающими ^ и $ до и после \n. Правая часть выполняется как программный код: perl -i -n -p -e's/(.)/lc($1)/g' *.html приводит все литеры во всех файлах *.html текущей директории к нижнему регистру.

18. Встроенные переменные в regex.

 

$1, $2, $3, $4, ..., $n ... содержат ссылки на найденный текст, только в том случае если regex был в круглых скобках:

 

s%<f(.*?)><(.*?)"><(.*?)">%$1 $2 $3%g;

внутри regex можно использовать переменные типа \1, \2, \3, \4, ... \n, ...

s/a href=(["'])(.*?)\1>/$2/g

найдет все урл, заключенные в двойные, одинарные и вообще без кавычек, находящиеся в документе.

для /(a.*b)|(mumu)/ в переменной $+ содержится $1 или $2.

$& содержит полный текст совпадения при последнем поиске.

$' и $` содержатся строки до и после совпадения

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

 

($at = $bt) =~ s!m(.*?)o!! #для строк

for(@mass1 = @mass2){s/umka/maugli/} #для массивов

$u = ($m=~s/a/b/g); #поменять $m и занести в $u число замен.

 

Если нужно выцепить только алфавитные символы, с учетом настроек locale, то регексп примерно такой: /^[^\W\d_]+$/в нем учитываются все не алфавитные символы, не цифры и не подчеркивания(для случая "ванька-встанька"), символ отрицания в группе [] - ^, т.е. найти все, что не [\W\d_], можно было написать и скажем так !~m/^(\W|\d|_)*/.

Для упрощения понимания сложных регулярных выражений можно воспользоваться их комментированием. Иногда правда можно только по виду регулярного выражения определить зачем оно предназначено:

 

$mmm{$1} = $2 while ($nnn =~ /^([^:]+):\s+(.*)$/m);

 

читаем регулярное выражение:

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

Что это может быть, вполне вероятно, что оно нужно для составления статистики писем, выцепление заголовка письма и его названия из mbox в хеш. По крайней мере это регулярное выражение подходит для данной задачи.

 

Рабочие программы, использующие регулярные выражения

 

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

 

Выделение чисел в математической записи

 

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

 

#!/usr/bin/perl

$_=qq~

1234

34 -4567

 3456

-0.35e-0,2

56grf45

-.034 E20

-.034 e2,01 -,045 e-,23

-,034 e201 3e-.20

-,045 e-,23 e-0.88

E-0.20

22

E-21

 -0.2 w    4 3

345

2 ^-,3

~;

print "$1\n" while

 m%(([+-]?(?=\d|[\.,]\d)\d*([\.,]\d*)?((\se|e|\s?\^)

([-+]?\d*[,\.]?)\d+)?)|([+-]?e[+-]?\d*[,.]?\d+))%gxi;

 

программа исправно выводит все числа. Разберем регулярное выражение

 

m%(([+-]?(?=\d|[\.,]\d)\d*([\.,]\d*)?((\se|e|\s?\^)

([-+]?\d*[,\.]?)\d+)?)|([+-]?e[+-]?\d*[,.]?\d+))%gxi;

 

в переменной $1 содержится то, что регулярное выражение находит в результате, т.е. m%(...)%gmi. m%((что-то)|([+-]?e[+-]?\d*[,.]?\d+))%gmi нужно для того, чтобы находить числа видаe-20 или E21(так в математике обозначают десятку в какой-то степени, например e-0,20 = 10-0,20 или E20 = 1021). Рассмотрим левое регулярное выражение "что-то" для чисел вида неe20 или E21:

 

([+-]?(?=\d|[\.,]\d)\d*([\.,]\d*)?((\se|e|\s?\^)([-+]?\d*[,\.]?)\d+)?)

[+-]? - есть ли в перед числом знак + или -. ? - если вообще есть что-то, находящееся внутри впереди стоящего [...]. Выкинем проверку знака, регексп сократится до

 

(?=\d|[\.,]\d)\d*([\.,]\d*)?((\se|e|\s?\^)([-+]?\d*[,\.]?)\d+)?

Рассмотрим regex (?=\d|[\.,]\d)\d*логический оператор (?=B)требует, чтобы перед числом было B. В данном случае B представляет из себя regex \d|[\.,]\d Regex \d|[\.,]\d значит, что перед каждым числом должно быть что-то либо просто число, либо число, перед которым стоит либо запятая, либо точка, т.е. находим все числа вида ,2 .2 или просто числа 2(2 выбрано для примера, может быть и 3). Далее скобка закрывается и идет \d*, т.е. число вида,2 точно пройдет, а вот число вида ,223 не пройдет. Да и regex (?=\d|[\.,]\d)говорит о том, что нужно найти только одну цифру после запятой. Для остальных цифр и нужен квантификатор \d*, который значит любое количество цифр, в том числе и ноль, т.е. оно работает и для числе вида .2 или ,2 Далее идет регулярное выражение ([\.,]\d*)? которое говорит о том, есть ли вообще точка и запятая(здесь всю полную строчку в принципе можно усовершенствовать) и число \d*(в том числе и его отсутствие, ведь квантификатор * значит любой символ в том числе и ноль). Отбрасывая все что было выше от этого большого регулярного выражения остается строчка:

 

((\se|e|\s?\^)([-+]?\d*[,\.]?)\d+)?

Эта строчка отвечает за поиск в строке $_ математических обозначений степеней типа e201, E,20(число в степени 0,20 например a-0,20) и т.д. но только для подстрок вида -,034 e201. Заметьте, что в конце стоит знак вопроса, т.е. если степенное обозначение вообще существует. (\se|e|\s?\^) есть ли числа вида -,034 e201 или -,034e201 и числа в "компьютерной" записи вида 2 ^-,3 = 2-0,3, т.е. этим регекспом мы разрешили пользователю ставить или не ставить пробел при указании степени и разрешили писать значек ^ с пробелом перед ним(если есть). Далее идет выражение ([-+]?\d*[,\.]?), которое говорит о том, что степень может быть с + или - (типа e,-23 где юзер забыл поставить нолик, а на самом деле хотел написать a-0,23). Дальше идет цифра \d* (а может и не идет, т.к. квантификатор то *). Потом идет либо точка либо запятая(причем тут негласно введено ограничение на использование запятой/точки, после e, если степень дробная или вообще есть, точка или запятая должна быть, иными словами не имеет смысла написать -2,34e-,23, хотя юзер на самом деле хотел написать число-2,34-0,23). Наконец мы добрались до конца: идет \d+, но тут уж, пользователь, будь добр напиши хотя бы одно число, т.к. квантификатор +, а не * после \d. Т.е. наложили своего рода ограничения здравого смысла, можно просто написать 2, а можно написать и 2e,- что суть бессмыленно. И еще, m%(что-то)%igmстоит квантификатор i, который разрешает e быть и заглавным и квантификатор x, который разрешает разносить регулярное выражение на несколько строк.

Итак, регулярным выражением

 

m%(([+-]?(?=\d|[\.,]\d)\d*([\.,]\d*)?((\se|e|\s?\^)

([-+]?\d*[,\.]?)\d+)?)|([+-]?e[+-]?\d*[,.]?\d+))%gxi;

 

были предусмотрены числа степенного порядка, просто числа, числа со знаком, нецелые числа вида ,3(которое есть 0,3 или 0.3), ошибки пользователя при вводе чисел (типа -.034 e2,01 хотя надо бы писать либо -,034 e2,01 либо -.034 e2.01 хотя по смыслу перед точками и запятыми нужно ставить нули, но мы предусмотрели и это) и числа в "компьютерном" представлении.

Конечно, данное регулярное выражение не претендует на абсолютную работу, т.к. оно успешно не работает на подстроках вида -,045 e -,23 e-0.88 считая -,045 отдельным числом, а -,23 возводит в степень e-0.88, хотя по идее должно было бы быть два числа -,045 e -,23 и e-0.88, в таком случае еще одно ограничение пользователю: если хочется, чтобы степенные числа понимались корректно(для этой программы), то нельзя ставить пробел перед степенью e.

 

Облегчение поиска работы

 

Допустим,вы оказались без работы, развалилась ваша фирма или еще какая-нибудь причина. Вам требуется найти новую. Для упрощения этой задачи есть следующий скрипт, который находит по нужной позиции(веб программирование, зарплата от 200$ и т.д.) с www.job.ru все заявки за последние 10-15 дней, точнее емайлы, куда нужно слать резюме, что значительно убыстряет поиск работы(имея базы адресов легче разослать одно и то же резюме, используя нехитрый список рассылки):

 

#!/usr/bin/perl -wT

$url0="http://www.job.ru/cgi/list1.cgi?GR_NUM=";

$url1="%31&TOPICID=9&EDUC=2&TP=&Gr=&SEX=&AGEMIN=23&AGEMAX=&MONEY=200&CDT=";

$url2="&LDAY=99&ADDR=%ED%CF%D3%CB%D7%C1&KWORD=&KW_TP=AND";

use LWP::Simple;

foreach($i=1; $i<=57; $i++){#57 числолистаемыхстраниц

$plus.="%31%2B";

$test=$url0.$plus.$url1.$url2,"\n";

@mass=grep{s/(.*) ([\w+\-\.]+\@[\w\-\.]+\.\w{2,3})(.*)/$2/ig} split /\n/, get "$test";

$test.=join "\n", @mass;

$test.=\n";

}

@un=grep{!$test{$_}++} split /\n/, $test;

print join "\n", @un;

print "\nВы можете отправлять по вашей специальности $#un резюме\n";

 

Что делает эта программа?Она составляет GET запрос из параметров, которые скрыты в hidden полях навигации по результатам запроса на www.job.ru. Программа при помощиSimple.pm отправляет запрос на сервер и как бы листает странички с поиском. Критерий ваших профессиональных навыков составлен в GET-запросе и осталось только разослать почту(для этого можно написать список рассылки) по адресам, которые выдала программа. Разберем регулярное выражение для вытаскивания почтового адреса из текущей странички

 

s/(.*) ([\w+\-\.]+\@[\w\-\.]+\.\w{2,3})(.*)/$2/ig.

 

[\w+\-\.]\@ - найти все, что содержит буквы, тире и точки до символа @, ведь почтовый адрес по спецификации может быть вида aa.ss-ss@chto-to.ru. Тоже самое после символа @ -[\w\-\.]+ далее может быть точка \. и любая буква от 2 до 3 символов \w{2,3}, т.е. окончание, самый верхний домен .com, .ru, .cz и т.д. Далее регулярное выражение состоит из трех классов скобок(.*) - переменная $1, ([\w+\-\.]+\@[\w\-\.]+\.\w{2,3}) переменная $2 и все остальное в (.*) - $3. Пробел перед $2 стоит потому, что так устроен html, отдаваемый пользователю поиском по базе предложений о работе www.job.ru. Нам нужно содержимое $2, в котором находится e-mail работодателя. Пишем его во вторую часть s/наш regex/$2/ig. Квантификатор i нужен для того, чтобы не различать регисты Vasya@pupkin.ru и vasya@pupkin.ru, квантиикатор g задействова на тот случай, если работодатель указывает 2 адреса, по которым нужно высылать резюме. На 23 августа 2001 года на 20 часов 10 минут программа выдала 410 e-mail адресов(пролистав за 3-4 минуты 57 страниц), где вас ждут, как потенциального сотрудника.

Остается написать скрипт почтовой рассылки по e-mails, выданным данным скриптом. Но это в другой главе.

Примером выше был получен список email адресов. Теперь необходимо проверить, действительно ли существуют домены, на которых заведены такие пользователи(примитивная - но проверка).

 

#!/usr/bin/perl










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

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