Perl 如何使用';s//';如果我的字符串包含一个'/';?

Perl 如何使用';s//';如果我的字符串包含一个'/';?,perl,Perl,我在Mac10.6.6上使用Perl5.10.6。我想对一个文件执行一个简单的搜索和替换,因此我尝试: my $searchAndReplaceCmd = "perl -pi -e 's/\\Q${localTestDir}\\E//g' ${testSuiteFile}"; system( $searchAndReplaceCmd ); 但是上面的问题是变量$localTestDir包含目录分隔符(“/”),这会破坏正则表达式 在操作员期望的-e线1附近找到Bareword “s/\Q/ho

我在Mac10.6.6上使用Perl5.10.6。我想对一个文件执行一个简单的搜索和替换,因此我尝试:

my $searchAndReplaceCmd = "perl -pi -e 's/\\Q${localTestDir}\\E//g' ${testSuiteFile}";
system( $searchAndReplaceCmd );
但是上面的问题是变量
$localTestDir
包含目录分隔符(
“/”
),这会破坏正则表达式

在操作员期望的-e线1附近找到Bareword “s/\Q/home/selenium”

在运算符应位于-e的位置找到反斜杠 第1行,靠近“Live\”的语法错误位于-e第1行,靠近 “s/\Q/home/selenium”

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


当所讨论的变量包含正则表达式字符时,如何对文件执行搜索和替换?谢谢

似乎
$localTestDir
/
开头

通过将regex分隔符更改为
/
以外的内容进行补救:

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

发件人:

最后一个示例显示
s//
可以使用其他分隔符,例如
s
s{}{}
,甚至
s{}/
。如果使用单引号
s'
,则 regex和replacement被视为单引号字符串


更改分隔符很有用,但更一般地说,您可以在任何正则表达式字符前面加上反斜杠,使其成为非特殊字符


因此,s/\/abc/\/xyz/将起作用,尽管它的可读性不是很好。

问题是,为什么要在perl中,通过shell,在perl中进行搜索和替换。这似乎是一种迂回的处理方式,您将遇到shell插值的问题

\Q\E
应该覆盖字符串中的特殊字符,因此
/
不应该是一个问题。发件人:

这里有一个替代方案(未经测试),全部是perl解决方案。如果您想更加确定,请将
/
分隔符交换为其他内容,例如
s###
(您可以使用任何字符作为分隔符)


问题是,
$localTestDir
的替换太快了

这里有一种方法可以让您对重新分隔符使用
/

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

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

又名“倾斜牙签综合症”:)@Dave Perl非常可爱;)系统调用可能很方便,但几乎总是最好使用纯perl IMO。但是如果
$localTestDir
包含
,该怎么办呢
?@user5402:看看
perlrequick
中的示例,使用另一个分隔符:
s####
s,,,,
s
s{}/
,等等。我的观点是,在知道
$localTestDir
是什么之前,必须选择一个分隔符。如果
$localTestDir
包含所有ASCII字符怎么办?现在你该怎么办?@user5402:放一个反斜杠,当然,在中还有
quotemeta
选项
\Q          quote (disable) pattern metacharacters till \E
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 $!;
use strict;
use warnings;
use Tie::File;

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

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