Сохранить цитаты в аргументах bash
Я создаю bash script, который будет печатать и передавать сложные аргументы другой внешней программе.
./script -m [email protected],[email protected] -o -q -- 'uptime ; uname -a'
Как распечатать необработанные аргументы как таковые:
-m [email protected],[email protected] -o -q -- 'uptime ; uname -a'
Использование [email protected]
и $*
удаляет одинарные кавычки вокруг uptime ; uname -a
, которые могут вызвать нежелательные результаты. Моему script не нужно анализировать каждый аргумент. Мне просто нужно распечатать/записать строку аргумента и передать их в другую программу, точно как они указаны.
Я знаю, что могу избежать цитат с чем-то вроде "'uptime ; uname -a'"
, но я не могу гарантировать, что пользователь это сделает.
Ответы
Ответ 1
Кавычки удаляются до того, как аргументы передаются на ваш script, поэтому слишком поздно их сохранить. Что вы можете сделать, так это сохранить их эффект при передаче аргументов во внутреннюю команду и восстановить эквивалентную цитированную/экранированную версию аргументов для печати.
Для передачи аргументов внутренней команде "[email protected]"
- с двойными кавычками [email protected]сохраняет исходные разрывы слов, что означает, что внутренняя команда получает точно такой же список аргументов, что и ваш script.
Для печати вы можете использовать формат% q в команде bash printf для восстановления цитирования. Обратите внимание, что это не всегда приведет к восстановлению исходного цитирования, но построит эквивалентную цитату/экранированную строку. Например, если вы передали аргумент 'uptime ; uname -a'
, он может печатать uptime\ \;\ uname\ -a
или "uptime ; uname -a"
или любой другой эквивалент (см. Ответ @William Pursell для аналогичных примеров).
Вот пример их использования:
printf "Running command:"
printf " %q" innercmd "[email protected]" # note the space before %q -- this inserts spaces between arguments
printf "\n"
innercmd "[email protected]"
Ответ 2
Если вы хотите напечатать список аргументов как можно ближе к тому, что пользователь, возможно, ввел:
#!/bin/bash
chars='[ !"#$&()*,;<>?\^`{|}]'
for arg
do
if [[ $arg == *\'* ]]
then
arg=\""$arg"\"
elif [[ $arg == *$chars* ]]
then
arg="'$arg'"
fi
allargs+=("$arg") # ${allargs[@]} is to be used only for printing
done
printf '%s\n' "${allargs[*]}"
Это не идеально. Аргумент типа ''\''"'
более сложный для размещения, чем это оправдано.
Ответ 3
Если пользователь вызывает вашу команду как:
./script 'foo'
первым аргументом, указанным в script, является строка foo
без кавычек. Невозможно отличить ваш script от этого и любого другого метода, с помощью которого он мог бы получить foo
в качестве аргумента (например, ./script $(echo foo)
или ./script foo
или ./script "foo"
или ./script \f\o""''""o
)).