1

我尝试在 Perl 中替换文件全名的目录部分。类似于:在目录 'D:\Texts1' 中有文件名 'D:\Texts1\text1',想用 'D:\Texts2' 替换它,然后文件名将是 'D:\Texts2\text1'。

我试试这段代码:

$filename = 'D:\Texts1\text1';
$i = 'D:\Texts1';
$o = 'D:\Texts2';
$filename =~ s'$i'$o'g;

而且它没有生效。$filename 不会改变。我尝试使用类似的东西

$i = quotemeta('D:\Texts1');

但它也没有生效。

4

6 回答 6

2

这里有几个有效的答案,我想和我一起编译一个全面的答案,以使这篇文章更容易阅读:

根本原因

$i = 'D:\Texts1';

当用作正则表达式模式时,应该转义“\” - 正则表达式引擎想要的是一些终极格式,例如:D:\\Texts1。所以这不起作用,但是,至少有 4 种不同的方法来构建这种格式,如下所示。

还要注意,当 ' 用作匹配或替换语句的分隔符时,变量插值将被禁用,这会呈现$filename =~ s'$i'$o'g; 几乎没用。所以第一步,把它改成使用 / 或 {}

解决方案 1

使用quotemeta,这将有效地逃避“\”:

$filename = 'D:\Texts1\text1';
$i = quotemeta('D:\Texts1');
$o = 'D:\Texts2';
$filename =~ s/$i/$o/g;

解决方案 2

使用 \Q .. \E,其效果与 quotemeta 类似:

$filename = 'D:\Texts1\text1';
$i = 'D:\Texts1';
$o = 'D:\Texts2';
$filename =~ s/\Q$i\E/$o/g; # or s/\Q$i/$o/g also works

解决方案 3

显式转义字符串中的“\”,并使用qr将字符串引用为正则表达式模式。

$filename = 'D:\Texts1\text1';
$i = qr 'D:\\Texts1';
$o = 'D:\Texts2';
$filename =~ s/$i/$o/g;

解决方案 4

转义到字符串准备好进行正则表达式的程度:

$filename = 'D:\Texts1\text1';
$i = 'D:\\\\Texts1';
$o = 'D:\Texts2';
$filename =~ s/$i/$o/g;
于 2012-08-17T16:16:19.807 回答
1

里面是问题\D:\Texts1您需要转义此元字符。为此,字符串应由\Qand包裹\E

$filename =~ s/\Q$i\E/$o/g;
于 2012-08-17T14:20:22.817 回答
1

这不会插入

$filename =~ s'$i'$o'g;

尝试使用/而不是',像这样:

$filename =~ s/$i/$o/g;

那应该工作。'防止字符串插值,因此变量名称显示为字符串文字。另外,请确保使用quotemeta您之前所做的方式。

于 2012-08-17T14:20:30.967 回答
0

你需要添加\Q

$filename =~s{\Q$i}{$o};
于 2012-08-17T14:21:16.987 回答
0

实际上,您遇到了两个问题的组合:

  • 单引号虽然作为正则表达式分隔符有效,但具有特殊含义:它们禁用变量插值。因此,您正在字符串中搜索文字模式$i(如果您启用了警告,您会得到一个线索——它告诉您变量 $i 和 $o 在您的程序中只使用一次)。
  • 正如其他人指出的那样,您还需要\Q...\E构造 orquotemeta()以避免将变量中的特殊字符解释为正则表达式运算符。
于 2012-08-17T14:48:55.063 回答
-1

更新代码

use strict;
use warnings qw/all/;

my $filename = 'D:\Texts1\text1';
my $i = 'D:\\Texts1';
my $o = 'D:\\Texts2';
$filename =~ s/\Q$i\E/$o/;

print $filename;

要开心!

于 2012-08-17T14:21:34.787 回答