如何在Perl单行中转义特殊字符以进行替换?

时间:2010-05-27 15:47:21

标签: perl

是否有某种方法可以替换@*?&等字符串,而无需在其前面添加“\”?

示例:

perl -pe 'next if /^#/; s/\@d\&/new_value/ if /param5/' test

在此示例中,我需要将@d&替换为new_value,但旧值可能包含任何字符,如何只转义需要转义的字符?

5 个答案:

答案 0 :(得分:11)

正如perldoc perlre所讨论的那样:

  

...今天更常见的是使用quotemeta()函数或“\ Q”metaquoting          转义序列禁用所有元字符的特殊含义:

/$unquoted\Q$quoted\E$unquoted/
  

请注意,如果在“\ Q”和“\ E”之间放置文字反斜杠(那些不在插值变量内),则双引号反斜杠插值可能          导致令人困惑的结果。如果你需要在“\ Q ... \ E”中使用文字反斜杠,请参阅perlop中的“解析引用结构的Gory细节”。

您还可以使用'作为s ///操作中的分隔符,以便按字面意思解析所有内容:

my $text = '@';
$text =~ s'@'1';
print $text;

在您的示例中,您可以执行(记下单引号):

perl -pe 's/\b\Q@f&\E\b/new_value/g if m/param5/ and not /^ *#/'

答案 1 :(得分:9)

你有几个问题:

  1. 您错误地使用\b
  2. 您正在用shell变量替换代码
  3. 您需要引用元字符
  4. 来自perldoc perlre

      

    单词边界(“\ b”)是两个字符之间的一个点,在其一侧有一个“\ w”

    字符@&均不是\w个字符。所以你的比赛肯定会失败。您可能希望使用s/(^|\s)\@d\&(\s|$)/${1}new text$2/

    之类的内容

    (^|\s)表示匹配字符串的开头(^)或空白字符(\s)。

    (\s|$)表示匹配字符串的结尾($)或空白字符(\s)。

    要解决第二个问题,您应该使用%ENV

    要解决第三个问题,您应该使用\Q and \E转义序列来转义$ENV{a}中的值。

    把它们放在一起我们得到:

    #!/bin/bash
    
    export a='@d&'
    export b='new text'
    
    echo 'param5 @d&' | 
        perl -pe 'next if /^#/; s/(^|\s)\Q$ENV{a}\E(\s|$)/$1$ENV{b}$2/ if /param5/' 
    

    打印

    param5 new text
    

答案 2 :(得分:6)

其他答案已经涵盖了这个问题,现在这是你的元问题:Leaning Toothpick Syndrome。当分隔符和逃逸开始模糊时,它就会出现:

s/\/foo\/bar\\/\/bar\/baz/

解决方案是使用不同的分隔符。您几乎可以使用任何东西,但平衡的牙箍效果最佳。大多数编辑都可以解析它们,你通常不必担心逃避。

s{/foo/bar\\}{/bar/baz}

这是你的带有支撑分隔符的正则表达式。

s{\@d\&}{new_value}

眼孔更容易。

答案 3 :(得分:1)

如果你真的想避免输入\,请将搜索字符串放入变量中,然后在你的正则表达式中使用它。在这种情况下,您不需要quotemeta\Q ... \E。例如:

my $s = '@d&';
s/$s/new_value/g;

如果你必须在单行中使用它,请记住如果使用“s来包含你的perl代码,你将不得不逃避$,或者逃避' s如果您使用'来包含您的perl代码。

答案 4 :(得分:0)

如果您有类似这样的字符串

my $var1 = abc$123

,并且要用abcd替换它,则必须使用\ Q \ E。如果不这样做,那么无论什么perl都不会替换字符串。

这是唯一对我有用的东西。

my $var2 = s/\Q$var1\E/abcd/g;