Прежде чем я попытаюсь ответить, у меня есть несколько предупреждений.Я не уверен, какова реальная цель здесь, поэтому, в зависимости от того, что это, есть несколько потенциальных проблем.
Во-первых, вообще невозможно восстановить, как строка цитировалась / экранировалась в командной строке.потому что есть много разных способов выразить одну и ту же строку в синтаксисе оболочки.Например, все следующие команды передают echo
один и тот же аргумент и, следовательно, выводят одно и то же:
echo This\ is\ a\ special\ character\ string.\ \\\~\`\!\@\#\$\%\^\&\*\(\)\-\=\+\[\]\{\}\|\;\:\'\"\,\<\>\/\?
echo This\ is\ a\ special\ character\ string.\ \\~\`\!@#\$%^\&*\(\)-=+[]{}\|\;:\'\",\<\>/?
echo 'This is a special character string. \~`!@#$%^&*()-=+[]{}|;:'"'"'",<>/?'
echo $'This is a special character string. \~`!@#$%^&*()-=+[]{}|;:\'",<>/?'
...and many more
(Примечание: технически вторая из этих может передать что-то другое, если текущий каталог содержит один или несколько файлов с конкретными действительно странными именами.)
Во-вторых, некоторые версии echo
выполняют дополнительную обработку escape.Некоторые делают это только тогда, когда передано значение -e
.Некоторые выдают «-e», если вы пытаетесь передать опцию -e
.Это беспорядок.
В-третьих, что нужно избегать и как на самом деле зависит от того, для чего вы собираетесь его использовать (и, в частности, как он будет анализироваться).В разных ситуациях используются разные правила синтаксического анализа, и вам необходимо добавить экранированные символы, соответствующие конкретной обработке, которой будет подвергаться вывод.В своем ответе я сконцентрировался на обращении к конкретному экранированию в вашем примере.
Мое решение: вы можете использовать sed
в конвейере, чтобы добавить экранирование перед любым списком символов, указанным в виде выражения в скобках.Это немного сложно, потому что «]» и «-» - это разделители в выражении в скобках;хитрость заключается в том, чтобы указывать «]» в качестве первого символа и «-» в качестве последнего, поэтому их не принимают за другие значения.Кроме того, я собираюсь написать это как строку в одинарных кавычках, поэтому одинарные кавычки требуют специальной разметки.Например:
sed 's/[][ \~`!@#$%^&*()=+{}|;:'"'"'",<>/?-]/\\&/g'
Или как функция:
addESC() { sed 's/[][ \~`!@#$%^&*()=+{}|;:'"'"'",<>/?-]/\\&/g'; }
Пример:
$ echo This\ is\ a\ special\ character\ string.\ \\\~\`\!\@\#\$\%\^\&\*\(\)\-\=\+\[\]\{\}\|\;\:\'\"\,\<\>\/\? | addESC
This\ is\ a\ special\ character\ string.\ \\\~\`\!\@\#\$\%\^\&\*\(\)\-\=\+\[\]\{\}\|\;\:\'\"\,\<\>\/\?
Почему ваши попытки не сработали: в первом, printf
не читает с stdin, он ожидает аргументы.Третий пытается исправить это с помощью xargs
, но xargs
выполняет свой собственный анализ / удаление и анализ цитаты, что испортило его.Во втором случае <<<
принимает строку , а не команду ;чтобы применить его к выводу команды, вы должны использовать что-то вроде <<< "$(command)"
.Кроме того, во всех версиях bash printf %q
заключает в кавычки и / или экранируется специально для использования самим bash, что не соответствует экранированию в вашем примере.