2011-08-01 18 views
5

我在Mac 10.6.6上使用Perl 5.10.6。我想執行一個簡單的搜索和替換對文件,所以我嘗試:如果我的字符串包含'/',如何使用'///'?

my $searchAndReplaceCmd = "perl -pi -e 's/\\Q${localTestDir}\\E//g' ${testSuiteFile}"; 
system($searchAndReplaceCmd); 

,但上面的問題是變量$localTestDir包含目錄分隔符("/"),這螺絲了正則表達式...

裸詞發現,其中運營商預計將在-e 1號線,近 「S/\ Q /家/硒」

反斜槓發現其中運營商預計將在-e 1號線,靠近 「活\」 語法錯誤在-e線1附近 「S/\ Q /家/硒」在-e行沒有終止

搜索模式1.

我如何做一個搜索和文件替換當有問題的變量包含正則表達式字符?謝謝。

回答

2

問題是爲什麼你要在Perl中通過shell執行搜索並從perl中進行替換。看起來像是一種迂迴的做事方式,而且你會遇到shell插入的問題。

\Q ... \E應該覆蓋字符串中的特殊字符,因此/「應該」不成問題。從perlre

\Q   quote (disable) pattern metacharacters till \E 

這裏有一個替代(未經測試),所有的Perl的解決方案。如果您想額外確定,請將/分隔符更換爲其他內容,例如s###(您可以使用任何字符作爲分隔符)。

use strict; 
use warnings; 
use File::Copy; 

open my $fh, '<', $testSuiteFile or die $!; 
open my $out, '>', $testSuiteFile . ".bak" or die $!; 

while (<$fh>) { 
    s/\Q${localTestDir}\E//g; 
    print $out $_; 
} 

move($testSuiteFile . ".bak", $testSuiteFile) or die $!; 

或者使用Tie::File

use strict; 
use warnings; 
use Tie::File; 

tie, my @file, 'Tie::File', $testSuiteFile or die $!; 

for (@file) { 
     s/\Q${localTestDir}\E//g; 
} 
untie @file; 
+0

愛上所有的Perl解決方案! – Dave

+1

@Dave Perl非常可愛;)系統調用可以很方便,但使用純粹的perl IMO幾乎總是可取的。 – TLP

6

看起來$localTestDir已從/開始。

補救措施,通過改變正則表達式分隔符以外的東西比/

my $searchAndReplaceCmd = "perl -pi -e 's!\\Q${localTestDir}\\E!!g' ${testSuiteFile}"; 

perldoc perlrequick

$x = "A 39% hit rate"; 
$x =~ s!(\d+)%!$1/100!e;  # $x contains "A 0.39 hit rate" 

最後一個例子表明,s///可以使用其他分隔符,如如 s!!!s{}{},甚至s{}//。如果使用單引號s''',則 正則表達式和替換被視爲單引號字符串。

+1

但是如果'$ localTestDir'包含'!'會怎麼樣? – ErikR

+0

@ user5402:看看'perlrequick'中的例子,使用另一個分隔符:'s ###','s,','s <><>','s {} //'等。 – Zaid

+0

我的觀點是你必須在知道'$ localTestDir'是什麼之前選擇一個分隔符。如果'$ localTestDir'包含所有ASCII字符怎麼辦?現在你做了什麼? – ErikR

1

更改分隔符很有用,但更一般的情況是,您可以在任何正則表達式字符前面加一個反斜槓使其非特殊。

所以s/\/abc/\/xyz /將起作用,儘管它不是很可讀。

+1

aka'leaning-toothpick-syndrome':) – Zaid

0

的問題是,$localTestDir替換髮生得太快了。

這裏有一個方法,可以讓你用你重新分隔符/

system('perl', '-pi', 
     '-e', 'BEGIN { $dir = shift(@ARGV) };', 
     '-e', 's/\\Q$dir\\E//g', 
     $localTestDir, 
     $suiteTestFile 
); 

注意,這也保護了$suiteTestFile內容不被shell解釋。

相關問題