Re: re

From
Artem Chuprina (2:5020/400)
To
Vitaly Mayatskih
Date
2005-06-03T01:45:24Z
Area
RU.PERL
From: Artem Chuprina <ran+news@ran.pp.ru>

Vitaly Mayatskih -> Artem Chuprina  @ Thu, 02 Jun 2005 20:15:10 +0400:

 VM>>> первом и/или третьем паттерне есть совпадение. Т.е. хочется
 VM>>> конструкцию типа [^...], только для выражения.
 AC>> В perldoc perlre искать negative look-ahead.
 VM>         Да мне бы лучше подошло look-behind, но оно только fixed
 VM> length, к сожалению.

 AC>> Надеюсь, "или" ты выразить способен и сам...  А если хочешь, чтоб на
 AC>> примере показали - покажи пример.
 VM>         Есть, допустим, строка со сылкой, которую нужно выудить. Если это
 VM> html-ссылка, то не надо. Собственно говоря, 3-й паттерн не нужен, т.к. по
 VM> наличию 1-го понятно, что это html.

 VM> $line = 'lalala <a href="http://tra-lala.com">asd</a>';
 VM> $line =~ /
 VM> (?:\<a\s*href\s*=\s*[\'\"]\s*)  # вот у этого бы результат инвертировать

Кстати, за первым \s надо +, а не *.

 VM> (
 VM>  (?:(?:ht|f)tp\:\/\/)
 VM>  (?:[\w()'*~!.-]+)

И кстати, должен заметить, что знаки препинания . и !, когда последние,
обычно не относятся к URL.  Посему лучше бы заменить на
[\w()'*~!.-]*[\w()'*~-].  Да и внешние группировки у обоих подвыражений
лишние...

 VM> )
 VM> /x

Вообще напрашивается решение "честно парсить HTML и искать только в
интересующих фрагментах".  А так - я бы сделал бы что-то следующего
типа.  Предположим, что $urlre - переменная, содержащая подвыражение для
собственно URL.  Тогда мы пишем цикл вида

while ($line =~ /<a\s+href\s*=\s*(['"])$urlre\1|($urlre)/ig) {
        if ($2) {
                # нашли
        }
}

Модификатор g в скалярном контексте будет начинать следующий поиск от
конца предыдущего, и по правилу "преимущество имеет более ранний по
тексту", если есть возможность поматчить URL в <a href, именно он и
будет поматчен.  Матч будет, но $2 при этом - undef.  Поскольку матч
будет, то подвыражение, удовлетворяющее второй альтернативе, следующим
поиском рассматриваться не будет.

Тут, правда, есть еще призовая игра под названием "а правда ли, что в
других атрибутах тега тебя URL устроит?".  Если неправда - жить лучше
(просто первая альтернатива заметно усложнится).  Если правда - хуже,
поскольку никакого порядка на атрибутах никто не обещал.  Тоже можно, но
вот тут уже заведомо дешевле будет честно распарсить HTML.

-- 
Artem Chuprina
RFC2822: <ran{}ran.pp.ru> Jabber: ran@jabber.ran.pp.ru

В теории нет различия между теорией и практикой.  На практике - есть.
--- ifmail v.2.15dev5.3
 * Origin: Leninsky 45 home network (2:5020/400)
SEEN-BY: 50/203 520 400/462 450/159 186 208 451/30 452/25 100 454/9 455/15
SEEN-BY: 461/33 43 74 106 132 640 464/34 465/204 467/24 469/125 200 999 478/44
SEEN-BY: 478/65 550/5068 4600/126 4614/9 4616/3 4623/56 4625/8 9 4626/100
SEEN-BY: 4627/10 4632/10 4635/4 99 1024 4641/444 4642/27 48 4657/50 5000/76
SEEN-BY: 5001/50 5001 5002/76 5002 5003/34 5006/1 5007/1 5010/53 70 146
SEEN-BY: 5011/13 5012/8 5015/4 28 214 5020/52 115 118 128 133 150 154 175 194
SEEN-BY: 5020/400 486 545 549 600 639 642 715 744 758 794 830 921 958 968 982
SEEN-BY: 5020/1057 1100 1169 1212 1234 1523 1604 1626 1642 1653 1665 1826 1829
SEEN-BY: 5020/1922 1930 2013 2020 2044 2142 2200 2238 2345 2590 2908 4400 4441
SEEN-BY: 5021/2 3 5022/128 5023/11 5024/1 73 5025/19 750 5026/14 49 5030/49 69
SEEN-BY: 5030/195 382 436 556 611 920 966 1016 1039 1063 1339 1520 1688 1900
SEEN-BY: 5031/7 47 63 70 5032/11 20 5033/21 35 5034/8 5035/3 38 63 5036/1 13
SEEN-BY: 5037/21 36 5038/4 5040/33 47 5041/4 5042/13 5045/7 42 5047/47 5049/1
SEEN-BY: 5049/6 157 5050/9 41 5051/15 35 5053/16 38 5054/1 8 9 35 36 37 45 50
SEEN-BY: 5054/66 67 81 85 5055/177 5056/16 5057/1 5058/77 5059/2 9 20 5060/88
SEEN-BY: 5060/90 5061/15 120 5062/1 4 7 5063/51 5064/7 35 39 5066/18 5070/26
SEEN-BY: 5070/66 1222 5071/22 5075/5 37 5077/70 80 5079/49 5080/80 1003 5081/2
SEEN-BY: 5082/6 5083/13 21 5090/23 105 108 113 5093/4 27 33 5096/18 5100/113
SEEN-BY: 6001/3 6023/1 6033/2727 6035/9 6070/5 6083/11
PATH: 5020/400 4441 52 5054/1 37