regex - Perl - 变量插值和反冲(转义)如何在替换正则表达式中工作,特别是替换部分

标签 regex perl escaping interpolation substitution

我试图理解当变量或反斜杠或包含反斜杠的变量被放入正则表达式替换中时会发生什么,例如 s/$var1/$var2/s/abc\\/xyz\\/ 等...

这是我尝试过的:

use Modern::Perl; no strict;

$bs_a = "\\_a";
$bs_b = "\\_b";

$str_to_substitute = "C:\\tmp\\_a";
### I'm gonna change this string to C:\tmp\_b by regex substitution
### pattern part: $bs_a, replacement part: $bs_b
### using the whole strings instead of just s/a/b/ because for example
### I may have many such string pairs for substitutions in an external file

#1
$result = $str_to_substitute =~ s/\\_a/\\_b/r; 
say $result;  # C:\tmp\_b    ... OK

#2
$result = $str_to_substitute =~ s/\\_a/$bs_b/r; # 
say $result;  # C:\tmp\_b    ... OK

#3
$result = $str_to_substitute =~ s/$bs_a/$bs_b/r; # 
say $result;  # C:\tmp\\_b    ... why?? what is the difference between #1 and #3

#4
$result = $str_to_substitute =~ s'$bs_a'$bs_b'r; 
say $result; # $bs_a is literally '$bs_a', $bs_b also is literal

#5
$result = $str_to_substitute =~ s/$bs_a/\\_b/r;
say $result; # C:\tmp\\_b    ?? what is the difference between #1 and #5 (and #3)

我的想法是替换根本不会进行任何转义。 (图案部分)

现在我真的很困惑,我不明白为什么结果#1,#3和结果#1,#5不同。

  • 有人知道为什么吗?
  • 有谁知道当我将变量和反向间隙放入替换部件时会发生什么的易于理解的来源:-)? (或者在模式部分,但关于替换)

最佳答案

在情况 #3 和 #5 中,具有相同的输出,正则表达式模式是一个被分配了双引号字符串的变量,因此已对其进行了评估并进行了字符串插值;所以它有一个反斜杠字符,变量(模式)是\_a

因此,输入字符串中的 \_a 被匹配并替换,而输入中的其他 \ 仍然保留。

在情况 #1 中,反斜杠在模式中是正确的,并且由 details of the regex parsing 组成。一个被跳过但被保留。所以该模式既有 \\_a,它们是匹配和替换的。

示例:

say "\\_a" =~ s{ \\_ }{X}gxr;  #--> Xa

my $p = "\\_";
say "\\_a" =~ s{ $p }{X}gxr;  #--> \Xa

替换端始终作为双引号字符串进行插值,即使以字符串文字形式给出也是如此。 (嗯,受一些修饰符和分隔符的约束。)


我想补充一点,我们可以使用各种工具来帮助我们避免弄乱斜线,这总是一个好主意。 (双斜杠则为 Double-so :)

首先,有一些用于处理路径的库,这似乎是关于什么的,在这种情况下,您可能根本不需要正则表达式;请参阅File::Spec , Path::Class ,整体好用Path::Tiny .

对于正则表达式,有 quotemeta的转义符 \Q...\E,这可能有助于干净地定位这些反斜杠,而不必担心它们的特殊和/或部分特殊操作。

关于regex - Perl - 变量插值和反冲(转义)如何在替换正则表达式中工作,特别是替换部分,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/68692911/

相关文章:

r 系统函数 cd 进入带空格的文件夹名称

java 正则表达式 - 必需的字符串验证

perl - 如何在 pod2usage 中指定宽度?

security - 相当于 Golang 的 mysql_real_escape_string

perl - 为什么我的父进程在退出之前看不到子进程的输出?

perl - 如何动态创建替换?

javascript - CKEditor 和转义元素

regex - 查找字符串中是否存在反斜杠 Go

python - 如何使正则表达式匹配整个字符串?

java - 如何用匹配子字符串长度的一个字符替换字符串模式?