简体   繁体   English

Perl 使用变量搜索和替换,字符串包含点

[英]Perl search and replace using variables, string contains dot

I'm using a variable to search and replace a string using Perl.我正在使用变量来搜索和替换使用 Perl 的字符串。 I want to replace the string 23.0 with 23.0.1 , so I tried this:我想用23.0.1替换字符串23.0 ,所以我尝试了这个:

  my $old="23.0";
  my $new="23.0.1";
  $_ =~ s/$old/$new/g;         

The problem is that it also replaced the string 2310 , so I tried:问题是它也替换了字符串2310 ,所以我试过:

  my $old="23\.0"

and also /ee .还有/ee But can't get the correct syntax for it to work.但无法获得正确的语法使其正常工作。 Can someone show me the correct syntax?有人可以告诉我正确的语法吗?

There are two things that will help you here:有两件事可以帮助您:

The quotemeta function - that will escape meta characters. quotemeta函数 - 将转义元字符。 And also the \\Q and \\E regex flags, that stop regex interpolation.还有\\Q\\E正则表达式标志,停止正则表达式插值。

print quotemeta "21.0";

Or:或者:

my $old="23.0";
my $new="23.0.1";
my $str = "2310";
$str =~ s/\Q$old\E/$new/g;
print $str;

只需使用单引号并转义点即可。

my $old='23\.0';

To complement Sobrique's excellent answer, let me note that the reason your attempt with "23\\.0" didn't work is that "23\\.0" and "23.0" evaluate to the same string: in a double-quoted string literal, the backslash escape sequence \\.为了补充 Sobrique 的出色答案,让我注意您尝试使用"23\\.0"不起作用的原因是"23\\.0""23.0"计算为相同的字符串:在双引号字符串文字中, 反斜杠转义序列\\. simply evaluates to .简单地评估为. . .

There are several things you could do to avoid this:您可以做几件事来避免这种情况:

  • If you indeed want to match a fixed string, and don't need or want to include any special regexp metacharacters in it, you can do as Sobrique suggest and use quotemeta or \\Q to escape them.如果您确实想匹配固定字符串,并且不需要或不想在其中包含任何特殊的正则表达式元字符,您可以按照 Sobrique 的建议进行操作,并使用quotemeta\\Q来转义它们。

    In particular, this is almost always the correct solution if the string to be matched comes from user input.特别是,如果要匹配的字符串来自用户输入,这几乎总是正确的解决方案。 If you do want to allow some limited set of non-literal metacharacters, you can unescape those after running the pattern through quotemeta .如果您确实想允许一些有限的非文字元字符集,您可以通过quotemeta运行模式quotemeta转义它们。 For a simple example, here's a quick-and-dirty way to turn a basic glob -like pattern (using the metacharacters ? and * for "any character" and "any string of characters" repectively) into an equivalent regexp:举一个简单的例子,这里有一种快速而肮脏的方法可以将基本的类似glob的模式(分别使用元字符?*表示“任何字符”和“任何字符串”)转换为等效的正则表达式:

     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 ".*"
  • Conversely, if you want to have a literal regexp pattern in your code, without immediately matching it against something, you can use the qr// regexp-like quote operator, like this:相反,如果您想在代码中使用文字正则表达式模式,而不立即将其与某些内容进行匹配,则可以使用qr//类似正则表达式的引号运算符,如下所示:

     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

    Note that qr// has other effects beyond just allowing you to use regexp syntax in a string literal: it actually pre-compiles the pattern into a special Regexp object, so that it doesn't need to be recompiled every time it's used later.请注意, qr//除了允许您在字符串文字中使用 regexp 语法之外还有其他效果:它实际上将模式预编译为特殊的 Regexp 对象,以便以后每次使用时都不需要重新编译。 In particular, as a side effect, the string representation of a qr// regexp literal will usually not exactly match the original content, although it will be equivalent as a regexp.特别是,作为副作用, qr// regexp 文字的字符串表示通常不会与原始内容完全匹配,尽管它与 regexp 等效。 For example, say qr/\\b23\\.0(\\.0)?\\b/ will, on my Perl version, output (?^u:\\b23\\.0(\\.0)?\\b) .例如, say qr/\\b23\\.0(\\.0)?\\b/将在我的 Perl 版本上输出(?^u:\\b23\\.0(\\.0)?\\b)

  • You could also just use a normal double-quoted string literal, and double any backslashes in it, but that's (usually) less efficient than using qr// , and also less readable due to leaning toothpick syndrome .您也可以只使用普通的双引号字符串文字,并将其中的任何反斜杠加倍,但这(通常)比使用qr//效率低,而且由于倾斜牙签综合症,可读性也较差。

    Using a single-quoted string literal would be slightly better, since backslashes in a single-quoted string are only special when followed by another backslash or a single quote.使用单引号字符串文字会稍微好一些,因为单引号字符串中的反斜杠只有在后跟另一个反斜杠或单引号时才是特殊的。 Even so, readability can still suffer if you happen to need to match any literal backslashes in your regexp, not to mention that it's easy to create subtle bugs if you forget to double a backslash in those rare places where it's still needed.即便如此,如果您碰巧需要匹配正则表达式中的任何文字反斜杠,可读性仍然会受到影响,更不用说如果您忘记在那些仍然需要反斜杠的罕见地方加倍反斜杠,很容易产生微妙的错误。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM