Bash

在 Perl 正則表達式中將插值變數解釋為文字字元串

  • May 29, 2014

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

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這裡使用的匹配變數 ( ),以避免$1由於軟引號引起的 shell 插值。

一般來說,如果您使用 Perl 進行大量著色工作,我建議您使用一個模組來為您處理終端特性。例如,查看Term::ANSIColor

引用自:https://unix.stackexchange.com/questions/131960