2010-12-09 235 views
1

我有两个关于Regexp::Common qw/URI /和Perl正则表达式的问题。在Perl中,如何正确提取括在括号中的URL?

我使用Regexp::Common qw/URI/来解析字符串中的URI并删除它们。但是,当URI位于括号之间时,我遇到了一个错误。

例如:(http://www.example.com)

该错误是由引起“)”,并且当它尝试解析URI,应用程序崩溃。所以,我想两个定位:

  • 做一个简单的(或我是这么认为的)写入括号和)字符
  • Regexp::Common qw/URI/具有实现修复功能之间的空白。

在我的代码中,我试图实现正则表达式,但应用程序冻结。我已经试过的代码是这样的:

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/\)/ \)/;

BTW,我有一个关于Regexp :: Common qw/URI /的问题。我有两个字符串类型:

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

我想删除的URI,如果它是最后一个组件(和保存)。如果没有,则保存它而不将其从文本中移除。

+0

您应该阅读关于如何格式化您的帖子的提示。您无需输入实时链接即可在自己的帖子中添加一堆网址。而且,不需要在代码中插入`
`。 – 2010-12-09 13:59:01

回答

0
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"; 
} 

它打印的第一次“你好!我爱(谷歌)”。然后再次评估while循环条件。你的字符串仍然与你的正则表达式匹配(它仍然包含一个右括号),所以替换再次运行,这次它打印出两个空格的“Hello !!,我爱(GOOGLE)”。

然后继续。每循环一次,就会添加另一个空间,但每当您仍然有一个右括号时,就会运行另一个替换。

我能看到的最简单的解决方案是只匹配右括号,如果它前面有非空白字符(使用\ S)。

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

在这种情况下,循环只执行一次。

2

您不必首先测试匹配,以便能够正确使用s///运算符:如果字符串与搜索模式不匹配,它将不会执行任何操作。

#!/usr/bin/perl 

use strict; use warnings; 

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

print "$str\n"; 

在文本中正确检测URL的一般问题很容易出错。例如参见Jeff's thoughts on this

0

为什么不在搜索中包含括号?如果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"; 

从正则表达式::常见的正则表达式可以作为一个更长的正则表达式的一部分,它并不一定要在自己的使用。此外,我在正则表达式中使用了'x'修饰符来允许空格,这样您可以更清楚地看到发生了什么 - 带反斜杠的括号被视为匹配的字符,没有定义匹配的字符(可能类似于{-keep} - 我以前没有用过)。

你也可以将支架可选,喜欢的东西:

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

尽管这会导致两个匹配的变量,一个不确定的 - 就需要这样类似以下内容:

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

有可能是一个更好的方法来做到这一点,而且如果你不打扰匹配括号,那么你可以简单地在第一个正则表达式中使括号可选(通过'?')...

要回答你的第二个问题,只关于行尾的匹配URL - 看看正则表达式的“锚点”,它可以强制匹配一行的开头或结尾:^和$(或\ A和\ Z如果你更喜欢)。例如仅匹配一行末尾的网址:

/$RE{URI}\Z/