В Perl, как я могу правильно извлечь URL-адреса, заключенные в скобки? - PullRequest
1 голос
/ 09 декабря 2010

У меня два вопроса о Regexp :: Common qw / URI / и Regex в Perl.

Я использую Regexp::Common qw/URI/, чтобы проанализировать URI в строках и удалить их.Но у меня есть ошибка, когда URI находится в скобках.

Например: (http://www.example.com)

Ошибка вызвана ')', и когда он пытается проанализировать URI,сбой приложения.Итак, я подумал о двух исправлениях:

  • Сделайте простое (или я так думал), которое записывает пробел между круглыми скобками и ) символами
  • Regexp::Common qw/URI/ имеет функциюкоторые реализуют исправление.

В своем коде я пытался реализовать Regex, но приложение зависает.Код, который я попробовал, таков:

use strict;

use Regexp::Common qw/URI/;
my $str = "Hello!!, I love (http://www.example.com)";
while ($str =~ m/\)/){
                $str =~ s/\)/ \)/;
        }
my ($uri) = $str =~ /$RE{URI}{-keep}/;
print "$uri\n";
print $str;

Вывод, который я хочу получить: (http://www.example.com )

Я не уверен, но думаю, что проблема в $str =~ s/\)/ \)/;

Кстати, у меня вопрос по Regexp :: Common qw / URI /.У меня есть два типа строки:

  1. ablalbalblalblalbal http://www.example.com
  2. asfasdfasdf http://www.example.com aasdfasdfasdf

Я хочу удалить URI, если этопоследний компонент (и сохранить его).И, если нет, сохраните его, не удаляя его из текста.

Ответы [ 3 ]

2 голосов
/ 09 декабря 2010

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

#!/usr/bin/perl

use strict; use warnings;

my $str = "Hello!!, I love (GOOGLE)";
$str =~ s/\)/ )/g;

print "$str\n";

Общая проблема правильного определения URL в тексте подвержена ошибкам. См. Например мысли Джеффа об этом .

0 голосов
/ 09 декабря 2010

Почему бы просто не включить скобки в поиск?Если URL-адреса всегда будут заключены в квадратные скобки, то что-то вроде этого:

#!/usr/bin/perl
use warnings;
use strict;
use Regexp::Common qw/URI/;

my $str = "Hello!!, I love (http://www.google.com)";
my ($uri) = $str =~ / \( ( $RE{URI} ) \) /x;
print "$uri\n";

Регулярное выражение из Regex :: Common можно использовать как часть более длинного регулярного выражения, его не нужно использовать отдельно.,Также я использовал модификатор 'x' в регулярном выражении, чтобы разрешить пробелы, чтобы вы могли более четко видеть, что происходит - скобки с обратными слешами обрабатываются как совпадающие символы, а те, которые не определяют, что сопоставить (предположительно, как{-keep} - я не использовал это раньше).

Вы также можете сделать скобки необязательными, например:

/ (?: \( ( $RE{URI} ) \) | ( $RE{URI} ) ) /

, хотя это приведет к двум переменным соответствия,один неопределенный - поэтому понадобится что-то вроде следующего:

my $uri = $1 || $2 || die "Didn't match a URL!";

Возможно, есть лучший способ сделать это, а также, если вас не беспокоит совпадение скобок, вы можете просто сделать скобки необязательными (черезa '?') в первом регулярном выражении ...

Чтобы ответить на ваш второй вопрос, касающийся только совпадающих URL-адресов в конце строки, взгляните на регулярные выражения Regex, которые могут привести к совпадению с началомили конец строки: ^ и $ (или \ A и \ Z, если хотите).например, сопоставление URL только в конце строки:

/$RE{URI}\Z/
0 голосов
/ 09 декабря 2010
my $str = "Hello!!, I love (GOOGLE)";
while ($str =~ m/)/){
  $str =~ s/)/ )/;
}

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

my $str = "Hello!!, I love (GOOGLE)";
while ($str =~ m/)/){
  $str =~ s/)/ )/;
  print $str, "\n";
}

При первом выводе «Hello !!, I love (GOOGLE)».Условие цикла while оценивается снова.Ваша строка по-прежнему соответствует вашему регулярному выражению (она все еще содержит закрывающую скобку), поэтому замена выполняется снова, и на этот раз она выводит «Hello !!, I love (GOOGLE)» с двумя пробелами.

И такэто продолжается.Каждый раз в цикле добавляется еще один пробел, но каждый раз, когда у вас все еще есть закрывающая скобка, запускается другая подстановка.

Самое простое решение, которое я вижу, это сопоставить закрывающую скобку, только если ей предшествуетнепробельный символ (с использованием \ S).

my $str = "Hello!!, I love (GOOGLE)";
while ($str =~ m/\S)/){
  $str =~ s/)/ )/;
  print $str, "\n";
}

В этом случае цикл выполняется только один раз.

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