我在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行终止。
当有问题的变量包含正则表达式字符时,如何对文件进行搜索和替换?谢谢。
答案 0 :(得分:6)
似乎$localTestDir
以/
开头。
将正则表达式分隔符更改为/
以外的其他内容的补救措施:
my $searchAndReplaceCmd = "perl -pi -e 's!\\Q${localTestDir}\\E!!g' ${testSuiteFile}";
$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解释。