Le virgolette vengono rimosse prima che gli argomenti vengano passati allo script, quindi è troppo tardi per conservarli. Quello che puoi fare è preservare il loro effetto quando passi gli argomenti al comando interno e ricostruire una versione quotata/escape equivalente degli argomenti per la stampa.
Per passare gli argomenti al comando interno "[email protected]"
-- con le doppie virgolette, [email protected] conserva le interruzioni di parola originali, il che significa che il comando interno riceve esattamente lo stesso elenco di argomenti ricevuto dallo script.
Per la stampa, puoi usare il formato %q nel comando printf di bash per ricostruire la citazione. Nota che questo non ricostruirà sempre la citazione originale, ma costruirà un equivalente stringa quotata/con escape. Ad esempio, se hai passato l'argomento 'uptime ; uname -a'
potrebbe stampare uptime\ \;\ uname\ -a
o "uptime ; uname -a"
o qualsiasi altro equivalente (vedi la risposta di @William Pursell per esempi simili).
Ecco un esempio di utilizzo di questi:
printf "Running command:"
printf " %q" innercmd "[email protected]" # note the space before %q -- this inserts spaces between arguments
printf "\n"
innercmd "[email protected]"
Se l'utente invoca il tuo comando come:
./script 'foo'
il primo argomento dato allo script è la stringa foo
senza le virgolette. Non c'è modo per il tuo script di distinguere tra questo e qualsiasi altro metodo con cui potrebbe ottenere foo
come argomento (es. ./script $(echo foo)
o ./script foo
o ./script "foo"
o ./script \f\o""''""o
).
Se vuoi stampare l'elenco degli argomenti il più vicino possibile a ciò che l'utente ha probabilmente inserito:
#!/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[*]}"
Non è perfetto. Un argomento come ''\''"'
è più difficile da accogliere di quanto sia giustificato.