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 "example@unixlinux.online" -- con le doppie virgolette, example@unixlinux.online 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 "example@unixlinux.online" # note the space before %q -- this inserts spaces between arguments
printf "\n"
innercmd "example@unixlinux.online"
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.