2013-04-29 80 views
2

我有以下代碼:

my $sDatabase = "abc_def:xyz_comp."; 
if ($sDatabase =~ m/^(\w)*\:(\w*)\_em\.$/) 
{ 
    print "$1\:$2\.\n"; 
} 
else 
{ 
    print "$1\:$2\_em\.\n"; 
} 

,但我得到空$1$2。輸出是:

Use of uninitialized value in concatenation (.) or string at new_mscn_iden_parse.pl line 187. 
Use of uninitialized value in concatenation (.) or string at new_mscn_iden_parse.pl line 187. 
:_em. 

回答

4

該代碼會做你想要

my $sDatabase = "abc_def:xyz_comp."; 

$sDatabase =~ m/^(\w+):(\w+?)(_em)?\.$/ or die "Invalid data"; 
if ($3) { 
    print "$1:$2.\n"; 
} 
else { 
    print "$1:$2_em.\n"; 
} 
+0

。那麼我想要$ sDatabase =「abc_def:xyz_comp」。 請幫忙。 – 2013-04-29 19:32:20

+0

啊我明白了。好的,我修好了。 – Borodin 2013-04-29 19:47:16

+0

如何無條件地「打印」$ 1:$ 2 $ 3。\ n「'倖存了m //之後? – pilcrow 2013-04-29 20:44:55

3

你有什麼期望$1$2含有當你不匹配?

它包含您嘗試匹配之前包含的任何內容。

可能的解決方案:

$sDatabase =~ s/(?<!_em)(?=\.\z)/_em/; 
+0

$ 1應該有abc_def $ 2應該有xyz_comp – 2013-04-29 19:12:53

+0

這怎麼可能?模式不匹配。 – ikegami 2013-04-29 19:13:06

+0

但我仍然想在其他條件的結果。對不起,如果我沒有意義。這怎麼可能? – 2013-04-29 19:16:38

1

你有:

my $sDatabase = "abc_def:xyz_comp."; 
if ($sDatabase =~ m/^(\w)*\:(\w*)\_em\.$/); 

讓我們來看看這個匹配:

你」正則表達式說:

  • 錨定在行的開頭。
  • 您在尋找或更多單詞字符。字字符(在ASCII字母)包括小寫字母,大寫字母數字強調
    • 因此/\w*/將匹配以下所有:
    • 計算機
    • 計算機
    • computer23
    • computer_32
    • 一個空字符串
  • 接下來是你尋找一個冒號
  • 那麼,隨之而來的是_em
  • 多個單詞字符
  • 隨後一段
  • 這應該是字符串的結尾(如果沒有NL和你沒有做多行字符串搜索。看起來你在那裏安全)。

現在,讓我們看看你的字符串:abc_def:xyz_comp.

  • \w*將匹配高達abc_def。正則表達式是貪婪的,並儘可能匹配字符串的最大部分。
  • :將匹配冒號。到目前爲止,您匹配abc_def:
  • \w*將匹配xyz_comp
  • 現在,您正在嘗試匹配_em。哎呀!不好。字符串中沒有_em。您的正則表達式匹配將失敗。

因爲你的正則表達式匹配失敗,則$1$2變量根本沒有設置,沒有任何價值。

這就是爲什麼你會得到Use of uninitialized value。你可以做的是讓後來的表達的一半可選

my $sDatabase = "abc_def:xyz_comp."; 
if ($sDatabase =~ /^(\w)+:(\w*)(_em)?\.$/) { 
    if ($3) { 
     print "$1:${2}${3}.\n"; 
    else { 
     print "$1:${2}_em."; 
    } 
} 
else { 
    die qq(String doesn't match regular expression at all\n); 
} 

}

首先,我想你想至少匹配一個字符(我可能是錯的) ,因此我將匹配零個或多個的星號切換爲與一個或多個匹配的+

注意我有第三組圓括號,然後是?。這意味着匹配這個零或一個次。因此,只要您的字符串以一個或多個單詞字符開頭,後跟一個冒號,後跟一個或多個單詞字符,就會設置爲$1$2

不一定會發生的是$3將被設置。只有當您的字符串也以_em.結尾時纔會設置。如果您的字符串不包含_em,但以句點結尾,則$1$2仍將匹配。

在你的情況,我們可以通過這樣簡化它:

my $sDatabase = "abc_def:xyz_comp."; 
if ($sDatabase =~ /^(\w)+:(\w*)(?:_em)?\.$/) { 
    print "$1:${2}_em."; 
else { 
    die qq(String doesn't match regular expression at all\n); 
} 

(?:...)手段不設置匹配,只是組。因此,$3將永遠不會被設置。沒關係,無論是$ 3還是_em.,或者我們都會在比賽結束時加上_em.

+0

感謝您的詳細回覆! =) – 2013-04-29 21:54:25

+0

'(?:_ em)?'將始終與空字符串匹配。如果它存在,你最終會將_em加倍。 – ikegami 2013-04-29 22:31:48