quotemeta , которая реализует \Q
, абсолютно выполняет то, что вы просите
всем символам ASCII, не соответствующим /[A-Za-z_0-9]/
, будет предшествовать обратный слеш
Поскольку это предположительно в сценарии оболочки, проблема действительно состоит в том, как и когда переменные оболочки интерполируются и что видит программа Perl.
Лучший способ - избежать этой интерполяционной путаницы и вместо этого правильно передать эти переменные оболочки в однострочник Perl. Это можно сделать несколькими способами; см. этот пост для деталей.
Либо передавайте переменные оболочки просто как аргументы
#!/bin/bash
# define $target
perl -pe"BEGIN { $patt = shift }; s{\Q$patt}{$replacement}g" "$target" file.txt
где необходимые аргументы удаляются из @ARGV
и используются в блоке BEGIN
, так до выполнения; тогда file.txt
обрабатывается. Здесь нет необходимости в \E
в регулярном выражении.
Или используйте переключатель -s
, который включает переключатели командной строки для программы
# define $target, etc
perl -s -pe"s{\Q$patt}{$replacement}g" -- -patt="$target" file.txt
--
необходим для обозначения начала аргументов, а переключатели должны предшествовать именам файлов.
Наконец, вы также можете экспортировать переменные оболочки, которые затем можно использовать в скрипте Perl через %ENV
; но в целом я бы предпочел любой из вышеперечисленных подходов.
Полный пример
#!/bin/bash
# Last modified: 2019 Jan 06 (22:15)
target="/{"
replacement="&"
echo "Replace $target with $replacement"
perl -wE'
BEGIN { $p = shift; $r = shift };
$_=q(ah/{yes); s/\Q$p/$r/; say
' "$target" "$replacement"
Это печатает
Replace /{ with &
ah&yes
где я использовал символы, упомянутые в комментарии.
Другой способ
#!/bin/bash
# Last modified: 2019 Jan 06 (22:05)
target="/{"
replacement="&"
echo "Replace $target with $replacement"
perl -s -wE'$_ = q(ah/{yes); s/\Q$patt/$repl/; say' \
-- -patt="$target" -repl="$replacement"
, где код разбит на строки для удобства чтения (и, следовательно, требуется \
). Та же распечатка.