2016-04-03 64 views
0

我正在使用一個變量來搜索和替換使用Perl的字符串。 我想23.0.1替換字符串23.0,所以我想這:Perl搜索和替換使用變量,字符串包含點

my $old="23.0"; 
    my $new="23.0.1"; 
    $_ =~ s/$old/$new/g;   

的問題是,它也換成了串2310,所以我嘗試:

my $old="23\.0" 

,也/ee。 但是無法獲得正確的語法。有人能告訴我正確的語法嗎?

回答

3

有兩件事情,這將幫助你在這裏:

quotemeta功能 - 將逃跑元字符。還有\Q\E正則表達式標誌,停止正則表達式插值。

print quotemeta "21.0"; 

或者:

my $old="23.0"; 
my $new="23.0.1"; 
my $str = "2310"; 
$str =~ s/\Q$old\E/$new/g; 
print $str; 
+0

\ Q和\ E不是正則表達式的特徵,它們可以在你做雙引號插入的任何地方工作 – ysth

0

爲了補充Sobrique的出色答卷,讓我注意,有"23\.0"您嘗試沒有成功的原因是"23\.0""23.0"評估相同的字符串:在雙引用的字符串文字,反斜槓轉義序列\.簡單地計算爲.

有幾件事情你可以做些什麼來避免這種情況:

  • 如果你確實想匹配一個固定的字符串,並且不需要或不想要在任何特殊的正則表達式元字符,你可以按照Sobrique的建議並使用quotemeta\Q來逃避它們。

    特別是,如果要匹配的字符串來自用戶輸入,這幾乎總是正確的解決方案。如果你想要允許一些有限的非字面元字符集,你可以在之後通過quotemeta運行該模式,以避開那些。舉個簡單的例子,這裏是把一個基本glob樣模式(使用「任意字符」和repectively「的字符的任意字符串」元字符?*)成等價的正則表達式的快速和骯髒的方式:

    my $regexp = "^\Q$glob\E\$"; # quote and anchor the pattern 
    $regexp =~ s/\\\?/./g;  # replace "?" (escaped to "\?" by \Q) with "." 
    $regexp =~ s/\\\*/.*/g;  # replace "*" (escaped to "\*" by \Q) with ".*" 
    
  • 相反,如果你想在你的代碼中的字面正則表達式模式,不立即匹配它反對的東西,你可以使用qr//正則表達式樣報價運營商,像這樣:

    my $old = qr/\b23\.0(\.0)?\b/; # match 23.0 or 23.0.0 (but not 123.012!) 
    my $new = "23.0.1";    # just a literal string 
    
    s/$old/$new/g;   # replace any string matching $old in $_ with $new 
    

    注意qr//有其他影響除了只允許你在字符串文字中使用regexp語法外:它實際上是將模式預編譯成一個特殊的Regexp對象,所以以後每次使用它時都不需要重新編譯。特別是,作爲副作用,正則表達式字符串的字符串表示通常不會完全匹配原始內容,儘管它將作爲正則表達式等效。例如,在我的Perl版本中,say qr/\b23\.0(\.0)?\b/將輸出(?^u:\b23\.0(\.0)?\b)

  • 你也可以只使用一個正常的雙引號字符串文本,並在它的兩倍任何反斜槓,但是這(通常)比使用qr//效率較低,也不易閱讀,由於leaning toothpick syndrome

    使用單引號字符串文字會稍微好一些,因爲單引號字符串中的反斜槓只有在後跟另一個反斜槓或單引號時纔是特殊的。即便如此,如果您碰巧需要匹配正則表達式中的任何文字反斜槓,可讀性仍然會受到影響,更別提如果您忘記在仍然需要的罕見地方加倍反斜槓,就很容易造成細微的錯誤。