更新:

更新:

我用来perl给匹配的字符串着色

MATCH=aaa
printf "aaa\n/dev/aaa\nccc\n" | perl -pe "s/($MATCH)/\e[1;31m\1\e[0m/g"

这很有效,直到我尝试匹配包含特殊字符的字符串,例如

MATCH=/dev/
printf "aaa\n/dev/aaa\nccc\n" | perl -pe "s/($MATCH)/\e[1;31m\1\e[0m/g"

原因是,当bash替换时$MATCH,perl 得到以下表达式:

perl -pe "s/(/dev/)/\e[1;31m\1\e[0m/g"

我需要反斜杠才能/使其工作,即

MATCH=\/dev\/
printf "aaa\n/dev/aaa\nccc\n" | perl -pe "s/($MATCH)/\e[1;31m\1\e[0m/g"    

但我不知道MATCH会包含什么。它可以是任何东西,+或者(。有没有办法告诉我们perl按字面意思对待字符,而不是作为表达式?

更新:

使用建议的解决方案Joseph R.会出现以下错误:

MATCH=/dev/
printf "aaa\n/dev/aaa\nccc\n" | perl -pe "s/\Q($MATCH)\E/\e[1;31m\1\e[0m/g"
Backslash found where operator expected at -e line 1, near ")\"
(Missing operator before \?)
Having no space between pattern and following word is deprecated at -e line 1.
syntax error at -e line 1, near "s/\Q(/dev/)"
Search pattern not terminated at -e line 1.

更新2:

现在我没有收到任何错误,但似乎没有匹配(没有着色):

# MATCH=/dev/ ; printf "aaa\n/dev/aaa\nccc\n" | perl -pe 's/(\Q$ENV{MATCH}\E)/\e[1;31m\1\e[0m/g'
aaa
/dev/aaa
ccc

答案1

quotemeta是的,您可以使用带单引号的 Perl运算符:

export MATCH=...
... | perl -pe 's/(\Q$ENV{MATCH}\E)/...

\Q和之间的任何内容\E(如果没有提供,则直到正则表达式末尾\E)都被视为原样,元字符没有附加任何特殊含义。

等效地:

export MATCH=...
... | perl -pe '$sane=quotemeta $ENV{MATCH};s/($sane)/...

更新

这是如何做到的没有export:

MATCH=/dev/
printf "aaa\n/dev/aaa\nccc\n" \
 | perl -pe "\$sane=quotemeta q{$MATCH};s/(\$sane)/\e[1;31m\$1\e[0m/g"

请注意,您的代码有一个错误。您不能\1在 a 的替换模式中使用反向引用 ( ) s///,您需要使用匹配变量 ( $1) (我在这里使用的)\$1,以避免 shell$1由于软引号而进行插值。

一般来说,如果您使用 Perl 进行大量着色工作,我建议您使用一个模块来处理终端特性。查看术语::ANSIColor例如。

相关内容