如果我的字符串包含'/',我如何使用's ///'?

时间:2011-08-01 13:05:13

标签: perl

我在Mac 10.6.6上使用Perl 5.10.6。我想执行简单的搜索并替换文件,所以我尝试了:

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

但上面的问题是变量$localTestDir包含目录分隔符("/"),这搞砸了正则表达式......

  

Bareword发现运营商预计在-e第1行附近   “S / \ Q /家/硒”

     

反斜杠找到了运算符在-e所期望的位置   第1行,靠近-e第1行的“实时”语法错误   “S / \ Q /家/硒”

     

搜索模式未在-e第1行终止。

当有问题的变量包含正则表达式字符时,如何对文件进行搜索和替换?谢谢。

4 个答案:

答案 0 :(得分: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 :(得分: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;

答案 2 :(得分:1)

更改分隔符非常有用,但更常见的是,您可以在任何正则表达式字符前放置反斜杠,使其成为非特殊字符。

所以s / \ / abc / \ / xyz /会起作用,虽然它不是很易读。

答案 3 :(得分:0)

问题是$localTestDir的替换发生得太快了。

以下是一种方法,可让您使用/作为重新分隔符:

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

请注意,这也可以保护$suiteTestFile的内容不被shell解释。