Bash
在 Perl 正則表達式中將插值變數解釋為文字字元串
我
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。