2011-08-01 15 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解释。

相关问题