2010-12-09 55 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/