Perl регулярное выражение сопоставления infohash из ссылки магнита

Я пытаюсь извлечь информационный хеш из торрент-магнита с помощью регулярных выражений Perls
ссылка на магнит выглядит так:

Магнит: Xt= урна:btih:8AC3731AD4B039C05393B5404AFA6E7397810B41& дп = UBUNTU +11+10+ онейроидный + оцелот + рабочий стол + CD +i386& тр = HTTP%3A%2F%2Ftracker.openbittorrent.com%2Fannounce

но иногда это может выглядеть так:
Магнит: х = урна: btih: 8AC3731AD4B039C05393B5404AFA6E7397810B41

часть, которую я пытаюсь извлечь, это 8AC3731AD4B039C05393B5404AFA6E7397810B41

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

if ($tmpVar =~ m/magnet\:\?xt=urn\:btih\:([[:alnum:]]+?)/i) {
  $mainRes{'hash'} = $1;
}

я также попытался добавить &|$ после захвата, но это просто приводит к ошибке
Спасибо

3 ответа

Решение

Вы можете использовать:

/\burn:btih:([A-F\d]+)\b/i

Или если хеш всегда 40 символов:

/\burn:btih:([A-F\d]{40})\b/i

Как вы уже обнаружили, вы не хотите использовать ? в ваших регулярных выражениях. Вот почему:

? в pattern+? делает ваше регулярное выражение "нежадным", то есть оно будет пытаться использовать как можно меньше символов, в то же время соответствуя указанному вами шаблону. Так

"8AC3731AD4B039C05393B5404AFA6E7397810B41" =~ /(\w+?)/

просто возвращается8" в то время как

"8AC3731AD4B039C05393B5404AFA6E7397810B41" =~ /(\w+)/

возвращает всю строку.

if ($tmpVar =~ m/magnet:\?xt=urn:btih:([[:alnum:]]+)/i) {
    $mainRes{'hash'} = $1;
}

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

#!/usr/bin/perl
use URI;
use URI::QueryParam;
use Data::Dumper;

my $u = URI->new( shift() );
my $xt = $u->query_form_hash->{xt};

my ($hash) = $xt =~ m{^urn:btih:(.*)$};
print "$hash\n";

Предполагая ваш магнитный URI в командной строке.

Другие вопросы по тегам