2011-05-10 80 views
17

可以somone解釋爲什麼這個小perl腳本的輸出是「foofoo」(而不是「foo」)?具有全局替換的perl正則表達式中的奇怪行爲

#!/usr/bin/perl -w 
my $var="a"; 
$var=~s/.*/foo/g; 
print $var."\n"; 

沒有g選項,它的工作原理雖然它會,但爲什麼是全局選項匹配模式兩次?

在bash輸出爲預期

echo "a"|sed -e "s/.*/foo/g" 

任何解釋,將不勝感激 「foo」 的。

回答

12

首先.*匹配a,然後匹配a後的空字符串。也許你想要.+

+1

是的就是這樣,我確信'$ var =〜s /^.*/ foo/g;'沒有意識到它會匹配空字符串,但它實際上很明顯 – rcout 2011-05-10 15:37:18

+1

關於第二個想法,*是應該是貪婪的,怎麼回事? – rcout 2011-05-10 16:05:49

+2

@rcout:貪婪與重複匹配的次數有關,它不會以某種方式超過字符串的末尾 – ysth 2011-05-10 16:40:57

6

這是因爲你使用.*代替.+

的*修飾符告訴正則表達式引擎匹配(在你的榜樣替換)字符串「a」,然後是零長度字符串(和替換它也是如此)。

你可以在你的代碼示例使用此正則表達式測試:

$var=~s/(.*)/<$1>/g; 

然後,您會看到這樣的輸出:

"<a><>" 
6

如果添加re到您的代碼:

use re 'debug'; 

您將看到正則表達式成功匹配兩次:

Compiling REx `.*' 
size 3 Got 28 bytes for offset annotations. 
first at 2 
    1: STAR(3) 
    2: REG_ANY(0) 
    3: END(0) 
anchored(MBOL) implicit minlen 0 
Offsets: [3] 
     2[1] 1[1] 3[0] 
Matching REx ".*" against "a" 
    Setting an EVAL scope, savestack=5 
    0 <> <a>    | 1: STAR 
          REG_ANY can match 1 times out of 2147483647... 
    Setting an EVAL scope, savestack=5 
    1 <a> <>    | 3: END 
Match successful! 
Matching REx ".*" against "" 
    Setting an EVAL scope, savestack=7 
    1 <a> <>    | 1: STAR 
          REG_ANY can match 0 times out of 2147483647... 
    Setting an EVAL scope, savestack=7 
    1 <a> <>    | 3: END 
Match successful! 
Matching REx ".*" against "" 
    Setting an EVAL scope, savestack=7 
    1 <a> <>    | 1: STAR 
          REG_ANY can match 0 times out of 2147483647... 
    Setting an EVAL scope, savestack=7 
    1 <a> <>    | 3: END 
Match possible, but length=0 is smaller than requested=1, failing! 
          failed... 
Match failed 
foofoo 
Freeing REx: `".*"' 
8

更有趣,如果你嘗試

$var=~s/.*?/foo/g; 

你會得到

foofoofoo 

的?修飾符匹配1次或0次。如果除去克,你會得到

fooa

,因爲它只能更換空字符串,它找到的第一個。我喜歡perl。