是否有某种方法可以替换@
或*
或?
或&
等字符串,而无需在其前面添加“\”?
示例:
perl -pe 'next if /^#/; s/\@d\&/new_value/ if /param5/' test
在此示例中,我需要将@d&
替换为new_value
,但旧值可能包含任何字符,如何只转义需要转义的字符?
答案 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)
你有几个问题:
\b
单词边界(“\ 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;