Подтвердить что ты не робот

Сохранить цитаты в аргументах 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'", но я не могу гарантировать, что пользователь это сделает.

4b9b3361

Ответ 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)).