Script Bash per ricevere e ripassare i parametri citati


98

Sto cercando di ottenere parametri quotati di uno script bash per essere ricevuti in modo sicuro da uno script annidato. Qualche idea?

test.sh

#!/bin/bash
echo $*
bash myecho.sh $*

myecho.sh

#!/bin/bash
 echo $1
 echo $2
 echo $3
 echo $4

Campione:

bash test.sh aaa bbb '"ccc ddd"'

Risultato:

aaa bbb "ccc ddd"
aaa
bbb
"ccc
ddd"

Risultato desiderato

aaa bbb "ccc ddd"
aaa
bbb
ccc ddd

2
Stavo per fare quella domanda! Buon tempismo.
Scottie T

Risposte:


70
#!/bin/bash
echo $*
bash myecho.sh "$@"

Nota che il costrutto "$ @" non è specifico di bash e dovrebbe funzionare con qualsiasi shell POSIX (lo fa almeno con trattino). Nota anche che, dato l'output che desideri, non hai affatto bisogno del livello extra di quotazione. IE chiama semplicemente lo script sopra come:

./test.sh 1 2 "3 4"

5
"$ @" funziona con qualsiasi shell Bourne o derivata della shell Bourne (dal 1978 in poi), inclusi Korn e Bash. Probabilmente il 95% delle volte, l'uso di "$ @" è corretto e $ * è sbagliato.
Jonathan Leffler,

Bello! Ma conosci qualcuno se c'è un modo per memorizzarlo "così com'è" in una variabile? Originale$@ non è disponibile all'interno di una funzione (perché viene sovrascritto dagli argomenti della funzione). Ho provato foovar="$@"e foovar=$@+ "$foovar"nella funzione e nessuno ha funzionato: - /
bitifet

143

Si desidera utilizzare "$ @" (quotato in dollari) per passare i parametri a un pedice. Così ....

ls-color.sh:

#!/bin/bash
/bin/ls --color=auto "$@"    # passes though all CLI-args to 'ls'


Quanto al perché .....

Dalla pagina man di Bash :

$*- Si espande ai parametri posizionali, a partire da uno. Quando l'espansione avviene tra virgolette doppie, si espande in una singola parola con il valore di ogni parametro separato dal primo carattere della variabile speciale IFS. Cioè, "$*"è equivalente a "$1c$2c..." , dove c è il primo carattere del valore della variabile IFS. Se IFS non è impostato, i parametri sono separati da spazi. Se IFS è nullo, i parametri vengono uniti senza che intervengano separatori.

$@- Si espande ai parametri posizionali, a partire da uno. Quando l'espansione avviene tra virgolette doppie, ogni parametro si espande in una parola separata. Cioè, "$@"equivale a "$1" "$2" ...Se l'espansione tra virgolette si verifica all'interno di una parola, l'espansione del primo parametro viene unita alla parte iniziale della parola originale e l'espansione dell'ultimo parametro viene unita all'ultima parte dell'originale parola. Quando non ci sono parametri posizionali "$@"e non si $@espandono a nulla (cioè vengono rimossi).


Configurazione di alcuni script demo ...

echo 'echo -e "\$1=$1\n\$2=$2\n\$3=$3\n\$4=$4"' > echo-params.sh
echo './echo-params.sh $*' > dollar-star.sh
echo './echo-params.sh $@' > dollar-at.sh
echo './echo-params.sh "$*"' > quoted-dollar-star.sh
echo './echo-params.sh "$@"' > quoted-dollar-at.sh
chmod +x *.sh

"$@" - quoted-dollar-at è un file trasformazione dell'identità per ritrasmettere argomenti a una subshell (~ 99% delle volte, questo è ciò che intendevi fare):

./quoted-dollar-at.sh aaa '' "'cc cc'" '"ddd ddd"'
  # $1= aaa
  # $2=            
  # $3= 'cc cc'
  # $4= "ddd ddd"

"$*" - quotato-dollaro-stella rompe gli argomenti in una singola stringa (~ 1% delle volte in cui si desidera effettivamente questo comportamento, ad esempio in un condizionale :)if [[ -z "$*" ]]; then ...:

./quoted-dollar-star.sh aaa '' "'cc cc'" '"ddd ddd"'
  # $1= aaa  'cc cc' "ddd ddd"   
  # $2=                     
  # $3=             
  # $4=

$* / $@ - senza virgolette, entrambe le forme rimuovono un livello di virgolette e interpretano gli spazi dalle stringhe sottostanti ma ignorano i caratteri delle virgolette (quasi sempre, questo è un errore):

./dollar-star.sh aaa '' "'cc cc'" '"ddd ddd"'
  # $1= aaa
  # $2= 'cc                  
  # $3= cc'
  # $4= "ddd

./dollar-at.sh aaa '' "'cc cc'" '"ddd ddd"'
  # $1= aaa
  # $2= 'cc
  # $3= cc'
  # $4= "ddd

Se vuoi divertirti un po ', puoi usare "$ @" per annidare le cose nella profondità che desideri, spingendo e facendo scoppiare gli elementi dallo stack degli argomenti, se lo desideri.

function identity() {
  "$@"
}
set -x
identity identity identity identity identity echo Hello \"World\"
# + identity identity identity identity identity echo Hello '"World"'
# + identity identity identity identity echo Hello '"World"'
# + identity identity identity echo Hello '"World"'
# + identity identity echo Hello '"World"'
# + identity echo Hello '"World"'
# + echo Hello '"World"'
# Hello "World"

1
Grazie per la spiegazione. Ho appena usato "$ *" per l'alias grep.
buio

Mi salvi la giornata!
xyz
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.