我正在使用变量来搜索和替换使用Perl的字符串。
我想用23.0
替换字符串23.0.1
,所以我尝试了这个:
my $old="23.0";
my $new="23.0.1";
$_ =~ s/$old/$new/g;
问题是它还替换了字符串2310
,所以我尝试了:
my $old="23\.0"
以及/ee
。
但无法获得正确的语法来使其工作。有人能告诉我正确的语法吗?
答案 0 :(得分:3)
有两件事可以帮到你:
quotemeta
函数 - 将转义元字符。以及阻止正则表达式插值的\Q
和\E
正则表达式标志。
print quotemeta "21.0";
或者:
my $old="23.0";
my $new="23.0.1";
my $str = "2310";
$str =~ s/\Q$old\E/$new/g;
print $str;
答案 1 :(得分:1)
只用单引号引起来即可。
my $old='23\.0';
答案 2 :(得分:0)
为了补充Sobrique的优秀答案,请注意您"23\.0"
尝试无效的原因是"23\.0"
和"23.0"
评估相同string:在双引号字符串文字中,反斜杠转义序列\.
只评估为.
。
您可以采取以下措施来避免这种情况:
如果您确实希望匹配固定字符串,并且不需要或希望在其中包含任何特殊的正则表达式元字符,则可以按照Sobrique建议并使用quotemeta
或{{逃避他们。
特别是,如果要匹配的字符串来自用户输入,这几乎总是正确的解决方案。如果你做想要允许一些有限的非文字元字符,你可以在运行模式后通过\Q
取消那些。举一个简单的例子,这里是一种快速而又肮脏的方式来转换基本的glob式模式(使用元字符quotemeta
和?
来表示"任何字符& #34;和"任意字符串"分别为等效的正则表达式:
*
相反,如果您希望在代码中使用文字正则表达式模式,而不立即将其与某些内容进行匹配,则可以使用qr//
类似regexp的引号运算符,如下所示:
my $regexp = "^\Q$glob\E\$"; # quote and anchor the pattern
$regexp =~ s/\\\?/./g; # replace "?" (escaped to "\?" by \Q) with "."
$regexp =~ s/\\\*/.*/g; # replace "*" (escaped to "\*" by \Q) with ".*"
请注意my $old = qr/\b23\.0(\.0)?\b/; # match 23.0 or 23.0.0 (but not 123.012!)
my $new = "23.0.1"; # just a literal string
s/$old/$new/g; # replace any string matching $old in $_ with $new
除了允许您在字符串文字中使用regexp语法之外还有其他效果:它实际上将模式预编译为特殊的Regexp对象,因此它不需要每次用完以后重新编译。特别是,作为副作用,qr//
正则表达式文字的字符串表示通常与原始内容不完全匹配,尽管它将等同于正则表达式。例如,qr//
将在我的Perl版本上输出say qr/\b23\.0(\.0)?\b/
。
您也可以使用普通的双引号字符串文字,并将其中的任何反斜杠加倍,但这样(通常)效率低于使用(?^u:\b23\.0(\.0)?\b)
,并且可读性较低到leaning toothpick syndrome。
使用单引号字符串文字会略好一些,因为单引号字符串中的反斜杠只有在后跟另一个反斜杠或单引号时才是特殊的。即便如此,如果您恰好需要匹配正则表达式中的任何文字反斜杠,可读性仍然会受到影响,更不用说如果您忘记在那些罕见的地方加倍反斜杠,它很容易产生微小的错误。 ; s仍然需要。