Интерпретировать интерполированную переменную как литеральную строку в регулярном выражении 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. 

UPDATE2:

теперь я не получаю никаких ошибок, но похоже, что нет совпадения (нет раскраски):

 # 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 

One Solution collect form web for “Интерпретировать интерполированную переменную как литеральную строку в регулярном выражении Perl”

Да, вы можете использовать оператор 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" 

Обратите внимание, что ваш код ошибся. Вы не можете использовать backreference ( \1 ) в шаблоне замены s/// , вместо этого вам нужно использовать переменную match ( $1 ), которую я использовал как \$1 здесь, чтобы избежать интерполяции оболочки $1 потому что мягких котировок.

В общем, если вы делаете много раскраски с Perl, я бы предложил использовать модуль для обработки терминальных особенностей для вас. Обратите внимание на Термин :: ANSIColor .

  • Как проверить, соответствует ли имя файла шаблону?
  • Как работает опция -d для чтения bash?
  • Развертывание Jenkins не передается переменной java
  • выполнение сценария оболочки из запуска, медленное завершение / завершение сценария
  • Проверка правописания ввода пользователя по aspell, но как вызвать интерактивный режим в этом контексте?
  • Что делает эта линия в bash? Параметрируемая || имяскрипт
  • Лучший способ убить процессы, созданные скриптом bash?
  • Как автоматически сканировать документы на Linux с терминала?
  • Использование Grep In For Loop
  • Замените строку в файле на другую, где оба сохраняются в переменных
  • Избавиться от символов 000A в именах файлов
  • Linux и Unix - лучшая ОС в мире.