Не жадное сопоставление регулярных выражений в sed / perl - PullRequest
3 голосов
/ 20 июня 2011

Я делал sed /http.*.torrent/s/.*(http.*.torrent).*/\1/;/http.*.torrent/p 1.html для извлечения ссылок.Однако, так как в sed отсутствует не жадный квантификатор (который необходим, потому что далее в строке снова есть torrent), попытался преобразовать его в perl.Хотя нужна помощь с Perl.(Или, если вы знаете, как сделать это с помощью sed, скажите так.) perl -ne s/.*(http.*?.torrent).*/\1/ 1.html Теперь мне нужно добавить эту часть после преобразования из sed: /http.*.torrent/p

Это было частью sed /http.*.torrent/s/.*(http.*.torrent).*/\1/;/http.*.torrent/p 1.html

но это тоже не сработало;sed запустился, но не вышел, и когда я нажал клавиши, они повторили эхо и ничего больше.

Ответы [ 2 ]

4 голосов
/ 20 июня 2011

Я рекомендую позволить хорошо зарекомендовавшему себя модулю, такому как HTML :: LinkExtor , сделать тяжелую работу за вас и использовать регулярное выражение просто для проверки найденных ссылок. Посмотрите на пример ниже, насколько просто это может быть.

use Modern::Perl;
use HTML::LinkExtor;
use Data::Dumper;

my @links;


# A callback for LinkExtor. Disqualifies non-conforming links, and pushes
# into @links any conforming links.

sub callback {
    my ( $tag, %attr ) = @_;
    return if $tag ne 'a';
    return unless $attr{href} =~ m{http(?:s)?://[^/]*torrent}i;
    push @links, \%attr;
}


# The work is done here: Read the html file, parse it, and move on.
undef $/;
my $html = <DATA>;
my $p = HTML::LinkExtor->new(\&callback);
$p->parse( $html );

print Dumper \@links;

__DATA__
<a href="https://toPB.torrent" title="Download this torrent">The goal</a>
<a href="http://this.is.my.torrent.com" title="testlink">Testing2</a> <a href="http://another.torrent.org" title="bwahaha">Two links on one line</a>
<a href="https://toPBJ.torrent.biz" title="Last test">Final Test</a>
A line of nothingness...
That's all folks.

HTML :: LinkExtor позволяет настроить функцию обратного вызова. Модуль сам анализирует ваш HTML-документ, чтобы найти любые ссылки. Вы ищете ссылки «а» (в отличие от «img» и т. Д.). Таким образом, в вашей функции обратного вызова вы просто выходите как можно скорее, если у вас нет ссылки «а». Затем проверьте эту ссылку «a», чтобы увидеть, есть ли в ней название «torrent», в соответствующей позиции. Если это конкретное регулярное выражение не то, что вам нужно, вам нужно быть более конкретным, но я думаю, что это то, что вы хотели. Когда ссылки найдены, они помещаются в структуру данных. В конце моего тестового сценария я распечатываю структуру, чтобы вы могли видеть, что у вас есть.

Раздел __DATA__ содержит несколько примеров HTML-фрагментов, а также нежелательный текст для проверки того, что он только находит ссылки.

Использование хорошо протестированного модуля для анализа вашего HTML гораздо более долговечно, чем создание хрупких регулярных выражений для выполнения всей работы. Многие хорошо продуманные решения синтаксического анализа включают регулярные выражения под капотом, но только для того, чтобы делать небольшие кусочки работы здесь и там. Когда вы начинаете полагаться на регулярное выражение для выполнения анализа (в отличие от определения небольших строительных блоков), у вас быстро кончается газ.

Веселитесь.

3 голосов
/ 20 июня 2011

sed не имеет нежадного соответствия, поэтому лучше всего использовать perl:

perl -ne '/.*?(http.*?.torrent)/ && print "$1\n"' 1.html

Аргумент -n указывает perl читать каждую строку ввода (в данном случае из 1.html или из stdin, если на cmdline нет файлов) и запускать что-то для каждой строки ... 1007 * дает «что-то для выполнения» в командной строке.

Первая часть выражения совпадает с искомым выражением, а круглые скобки фиксируют ваши интересные биты в $1. Если он совпадает, он оценивается как true и затем выполняет печать (давая вам ваше совпадение вместе с символом новой строки).

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...