Архив рубрики: Регулярные выражения

Поиск ссылок на странице с помощью регулярного выражения

Обычно такие регулярные выражения бывают полезны для написания роботов-пауков. Решил потратить день, но написать одно регулярное выражение чтобы заменить им страницу программного кода, причем весьма запутанного. Но результат превзошел ожидания, программа уменьшилась на 250 строк!

Прелесть этого регулярного выражения в том, что оно не только вычисляет все внешние и внутренние ссылки, включая https и ftp ссылки, так ещё и дробит результат на отдельные элементы. Например можно затем проверять, какой протокол, адрес, имя сервера. Собственно результат предлагаю просмотреть самостоятельно в вашем языке программирования.

(<a)\s+(.*)(href)(\s*)(=)(\s*)([\"']|)(ftp://|https?://|/)([^'\"\s]+)\7(\s*)(.*)>(.*)</a>

В случае PHP нужно комментировать и символ «/», поэтому он будет выглядеть как «\/»
В целом простейший код на PHP для поиска ссылок может выглядеть вот так. Выражение «\7» из него пришлось убрать, так как в PHP-ом интерпретаторе это не работает. В моём учебнике про это предупреждали, что не во всех интерпретаторах эта функция есть. Поэтому выражение стало менее стабильным, может на каких то ссылках и будет глюкаться, но пока что я таковых не обнаружил.



$res=array();
$regEx = "/(<a)\s+(.*)(href)(\s*)(=)(\s*)([\"']|)(ftp:\/\/|https?:\/\/|\/)([^'\"\s]+)(\s*)(.*)>(.*)<\/a>/i";
//Заметьте, что это "жадный" вариант
//Ленивый будет различать ссылки расположенные подряд в одной строчке
//вот его версия, для использования раскомментировать нижнюю строчку:
//regEx="/(<a)\s+?(.*?)(href)(\s*?)(=)(\s*?)([\"']|)(ftp:\/\/|https?:\/\/|\/)([^'\"\s]+?)(\s*?)(.*?)>(.*?)<\/a>/i";
preg_match_all ($regEx,$txt,$res,PREG_SET_ORDER);

            echo '<br>';
                $npp=1;
                foreach ($res as $value) {
                    echo $npp++.". ";
                    for ($index1 = 0; $index1 < count($value); $index1++) {
                        $curvalue=$value[$index1];
                        echo "[ $curvalue ]";
                    }
                    echo "<br>\n";
                }

в переменную $res будет помещен двумерный массив с результатом. Подробнее о функции preg_match_all  можно прочесть здесь: http://phpclub.ru/manrus/f/preg-match-all.html

Это окончательный вариант, резличает ftp://, http://, https:// и относительные адреса. В $8 попадает протокол или «/» если это относительный адрес, а в $9 сам url без протокола, в $12 — текст анкора. URL может быть в одинарных кавычках, двойных кавычках или без кавычек. Исправлен недостаток: если написать такой «неправильный» тег, где адрес взят в кавычки таким образом, что открывается одинарная кавычка, к примеру, а закрывается двойная, этот шаблон воспринимал, как нормальную конструкцию. Теперь это исправлено.

Если нужно сграбить не ссылки, а картинки, тоже с выделением протокола и URL  в отдельные части массива, смотрите здесь http://www.bobpop.ru/?cat=14

Пользуйтесь на здоровье!
Реквизиты для благодярностей внизу страницы.

1C Выделене подстрок с помощью регулярного выражения

Пример тестировался на 1С 7.7, в 1С 8.х нужно только вместо «СоздатьОбъект» писать «Новый», ну и учитывать тот факт, что в восьмерке есть булев тип данных.

К примеру, перед нами задача, получить номер документа для вывода на печать налоговой накладной. Но в базе документы имеют примерно такие номера «FGT-00072», «AR-00120» и т.д. Если бы до тире было фиксированное число символов, можно было бы брать подстроку по знак «-«, затем брать из строки ту часть, которая стоит за минусом и применять чункцию Число(). В результате получим то, что нужно, то есть «FGT-00072» превратится в 72, а если вместо фиксированной части поиском найти позицию «-«, то и второй номер можно легко преобразовать. Но случаи бывают разные, я предлагаю создать универсальную функцию, с помощью которой вы можете находить любые подстроки, используя регулярное выражение.

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

Пример:

НомДокБН = регВырИгнорРегистр(Строка(«FGT-00072″),»([a-zA-Z]*)-?(0*?)([^0]\d*)»,2); //вернет «72»
ПостфиксБН = регВырИгнорРегистр(Строка(«03″),»(0*?)([^0]\d*)»,1);//Вернет «3» (универсальный убиратель ведущих нулей)

Мне такой подход понравился из-за универсальности, не нужно писать новые циклы и поиски с проверками под разные ситуации. Используем регулярное выражение и всё.

Собственно сама функция

//Выполняет поиск в строке по регулярному выражению
//номер позиции с нуля
//
функция регВырИгнорРегистр (текст, выражение, номерПозиции)
Если (ПустоеЗначение(текст)=1) ИЛИ (ПустоеЗначение(выражение) =1) ИЛИ (ПустоеЗначение(номерПозиции)=1) Тогда
возврат текст;
КонецЕсли;
Истина=-1;
Ложь=0;
RegExp = CreateObject(«VBScript.RegExp»);

RegExp.IgnoreCase = Истина; //Игнорировать регистр
RegExp.Global = Истина; //Поиск всех вхождений шаблона
RegExp.MultiLine = Ложь; //Многострочный режим

RegExp.Pattern = выражение; //Ищем вхождение
Matches=RegExp.Execute(текст);
ЧислоВхождений=Matches.Count();
Если ЧислоВхождений>0 Тогда
Match = Matches.Item(0);
SubMatches = Match.SubMatches;
SubMatch=SubMatches.Item(номерПозиции);
возврат (SubMatch);
Иначе
возврат «»;
КонецЕсли;
Возврат «»;
КонецФункции

1С 7.7 функция распознавания типа значения

Гениальное просто
Гениальное просто

Эта функция использует регулярные выражения vbscript и может делить любое переданное значение на: целое число, число вообще, дату и строку. Изначально нужно передавать строковой параметр, к примету «12,5», функция вернет «Число», а если передать «12», тогда вернет «ЧислоЦелое»

Возвращает: Определяемый тип, возвращаемый тип — строка. Возможные варианты: «Число», «ЧислоЦелое», «Строка», «Дата».

Обратите внимание, что если передать в качестве параметра строку «12.0», будет возвращен параметр «Число», а не «ЧислоЦелое».

Применение: Я использую для определения типа при чтении данных из различных файлов типа excel, csv или ADO таблиц.

Текст функции:

Функция глОпределитьТипЯчейкиADO(Значение)
//Разделяет типы на строку, число и дату
 Если ПустоеЗначение(Значение)=1 тогда
  возврат 0;
 конецЕсли;
Значение=Строка(Значение);
Истина=-1;
Ложь=0;
RegExp = CreateObject("VBScript.RegExp");

RegExp.IgnoreCase = Ложь; //Игнорировать регистр
RegExp.Global = Истина; //Поиск всех вхождений шаблона
RegExp.MultiLine = Ложь; //Многострочный режим
//есть ли буквы
RegExp.Pattern = "^[-\+]?\d+$";
 Если RegExp.Test(Значение)=Истина Тогда
 Возврат "ЧислоЦелое";
КонецЕсли;
RegExp.Pattern = "^[-\+]?\d*[.,]?[\d]{0,}$"; //число вообще (и целое и со знаками после точки или запятой)
Если RegExp.Test(Значение)=Истина Тогда
 Возврат "Число";
иначе
 RegExp.Pattern = "^\d{1,2}[\.\/-]([0]?\d|1[12])[\.\/-]\d{2,4}$"; //Дата
 //датой считает форматы вида 2.12.2014 , 01.12.14, 3.08.2014, 30-10-2014, 15/12/14 и т.д. первая цифра может быть
 //    одна или две. Цифр года 2, 3 или 4
 если RegExp.Test(Значение) = Истина Тогда
  Возврат "Дата";
 Иначе
  Возврат "Строка";
 КонецЕсли;
КонецЕсли;
КонецФункции

 

php регулярное выражение распознает email

для определения, введен ли правильный адрес email используйте такие регулярные выражения:

Статья была откорректирована и выражения переписаны. Недостатком прошлых выражений являлось то, что строка вида «tw32dream@mail.coca…com.ua» в которой идет три точки подряд тоже считалась правильным адресом электронной почты, что, в принципе нехорошо. Но я тогда ещё не додумался, как исправить данный момент. То есть первую точку после слова mail в нашем примере ещё мог контроллировать, а дальнейшие поддомены теоретически могут быть в любом количестве. Там было сложнее. Теперь эти недостатки исправлены.

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

если допустимы адреса на русском (имеется ввиду кириллица или другие языки, которые не пишутся на латинице)

— если не допускается точка в имени пользователя: мой_login@mail.ru :

^\w+@\w+(\.[\w]+)+$

— если точка в имени пользователя позволена: мой.login@mail.ru :

^[\w.]+@\w+(\.[\w]+)+$

 

если адреса допустимы только на латинице

— если не допускается точка в имени пользователя: my_login@mail.ru :

^[\da-zA-Z_]+@[\da-zA-Z_]+(\.[\da-zA-Z_]+)+$

— если точка в имени пользователя позволена: my.login@mail.ru :

^[\da-zA-Z_.]+@[\da-zA-Z_]+(\.[\da-zA-Z_]+)+$

 

Регулярное выражение ищет адреса изображений в html

(<img)\s+(.*)(src)(\s*)(=)(\s*)([«‘]|)(ftp:\/\/|https?:\/\/|\/)([^'»\s]+)\7(\s*)(.*)>

этот пример для VB, для PHP привожу пример прогаммного кода. Особенностью будет то, что нужно квотировать и символ /, то есть вместо него будет \/

Заметьте, что квантификаторы являются «жадными», поэтому, если изображения размещены по тексту без перевода строк, то браться будет только последнее. Для того, чтобы сделать его «ленивым», добавьте «?» в конце каждого квантификатора!

$res=array();
$regEx = «/(<img)\s+(.*)(src)(\s*)(=)(\s*)([\»‘]|)(ftp:\/\/|https?:\/\/|\/)([^’\»\s]+)\7(\s*)(.*)>/i»;
preg_match_all ($regEx,$txt,$res,PREG_SET_ORDER);

в переменную $res будет помещен двумерный массив с результатом. Подробнее о функции preg_match_all  можно прочесть здесь: http://phpclub.ru/manrus/f/preg-match-all.html

Это окончательный вариант, резличает ftp://, http://, https:// и относительные адреса. В $8 попадает протокол или «/» если это относительный адрес, а в $9 сам url без протокола. URL может быть в одинарных кавычках, двойных кавычках или без кавычек. Исправлен недостаток: если написать такой «неправильный» тег, где адрес взят в кавычки таким образом, что открывается одинарная кавычка, к примеру, а закрывается двойная, этот шаблон воспринимал, как нормальную конструкцию. Теперь это исправлено.

отличным преимуществом является то, что слово » src» (пробел, затем src) могут попадаться внутри тега IMG до собственно того самого src, который и есть адресом. А это может случиться, если такой текст написать например в title илил alt и разместить по тексту перед src. Такие случаи может единичны, может нулевые, но я считаю, что если знаю о недостатке, его следует исключить.

Так что выражение

<img title=»вытяжка адреса из src=» src=»http://my.ru/img/1.jpg» alt=»Ура!»> распознается абсолютно правильно, то есть — $8=http://, $9=my.ru/img/1.jpg

примеры
<img src=»http://my.ru/img/1.jpg» alt=»Ура!»> — $8=http://, $9=my.ru/img/1.jpg

<img src=»https://my.ru/img/1.jpg» alt=»Ура!»> — $8=https://, $9=my.ru/img/1.jpg

<img src=»ftp://my.ru/img/1.jpg» alt=»Ура!»> — $8=ftp://, $9=my.ru/img/1.jpg

<img src=»/img/1.jpg» alt=»Ура!»> — $8=/, $9=my.ru/img/1.jpg

Как использовать регулярное выражение в php, asp, vb и других языках программирования, читайте в соответствующем мануале по этим языкам.

Если хотите сграбить не изображения а ссылки с разделением по протоколу, смотрите мою статью на странице http://www.bobpop.ru/?p=271

Если желаете выразить благодарность в материальном виде, смотрите wm кошельки внизу страницы.