Добавить экранирование к специальным символам в строке (как функция) - PullRequest
0 голосов
/ 28 июня 2019

Итак, я ищу что-то похожее на работу:

$ echo This\ is\ a\ special\ character\ string.\ \\\~\`\!\@\#\$\%\^\&\*\(\)\-\=\+\[\]\{\}\|\;\:\'\"\,\<\>\/\?
This is a special character string. \~`!@#$%^&*()-=+[]{}|;:'",<>/?

Я хочу иметь возможность добавлять обратную косую черту только к специальным символам. Я видел примеры здесь, которые действительно работают, однако я не могу заставить их работать как функция pipable.

Вот как бы я хотел, чтобы это выглядело так:

$ echo This\ is\ a\ special\ character\ string.\ \\\~\`\!\@\#\$\%\^\&\*\(\)\-\=\+\[\]\{\}\|\;\:\'\"\,\<\>\/\? | addESC
This\ is\ a\ special\ character\ string.\ \\\~\`\!\@\#\$\%\^\&\*\(\)\-\=\+\[\]\{\}\|\;\:\'\"\,\<\>\/\?

$ echo This\ is\ a\ special\ character\ string.\ \\\~\`\!\@\#\$\%\^\&\*\(\)\-\=\+\[\]\{\}\|\;\:\'\"\,\<\>\/\? | addESC | addESC
This\\\ is\\\ a\\\ special\\\ character\\\ string.\\\ \\\\\\~\\\`\\\!\\\@\\\#\\\$\\\%\\\^\\\&\\\*\\\(\\\)\\\-\\\=\\\+\\\[\\\]\\\{\\\}\\\|\\\;\\\:\\\'\\\"\\\,\\\<\\\>\\\/\\\?

Использование bash на High Sierra.

Редактировать согласно запросу Андреаса

Пример использования экранирующих символов, которые я использовал для подтверждения работы, но не для функции: https://unix.stackexchange.com/questions/141312/how-to-escape-special-characters-in-a-string

Я пробовал:

$ echo This\ is\ a\ special\ character\ string.\ \\\~\`\!\@\#\$\%\^\&\*\(\)\-\=\+\[\]\{\}\|\;\:\'\"\,\<\>\/\? | printf '%q\n'

$ printf '%q\n' <<< printf '%q\n' <<< echo This\ is\ a\ special\ character\ string.\ \\\~\`\!\@\#\$\%\^\&\*\(\)\-\=\+\[\]\{\}\|\;\:\'\"\,\<\>\/\?

$ echo This\ is\ a\ special\ character\ string.\ \\\~\`\!\@\#\$\%\^\&\*\(\)\-\=\+\[\]\{\}\|\;\:\'\"\,\<\>\/\? | xargs printf '%q\n'

1 Ответ

0 голосов
/ 28 июня 2019

Прежде чем я попытаюсь ответить, у меня есть несколько предупреждений.Я не уверен, какова реальная цель здесь, поэтому, в зависимости от того, что это, есть несколько потенциальных проблем.

Во-первых, вообще невозможно восстановить, как строка цитировалась / экранировалась в командной строке.потому что есть много разных способов выразить одну и ту же строку в синтаксисе оболочки.Например, все следующие команды передают 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, что не соответствует экранированию в вашем примере.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...