Bash "for" loop senza una parte "in foo bar ..."


25

Recentemente stavo guardando un codice che mi ha confuso perché funziona e non me l'aspettavo. Il codice si riduce a questo esempio

#!/bin/bash
for var;
do
  echo "$var"
done

Se eseguito con argomenti da riga di comando, li stampa

$ ./test a b c
a
b
c

È questo, per me (inaspettato) inaspettato. Perché questo non provoca un errore perché varnon è definito? L'uso di questo è considerato una "buona pratica"?

Risposte:


27

fori cicli eseguono il ciclo sui parametri posizionali se nessuna in value1 value2...parte è specificata in tutte le shell tipo Bourne.

Questo era già il caso nella shell Bourne dalla fine degli anni '70, sebbene nella shell Bourne, dovresti ometterlo ;(puoi anche usarlo for i do(tranne in alcune vecchie versioni di cenere dove hai bisogno di una nuova riga prima del do)).

Vedi Qual è lo scopo della parola chiave "do" in Bash per i loop? per ulteriori informazioni tra cui varianti più sorprendenti .

fare:

for i
do
  something with "$i"
done

è una buona pratica. È leggermente più portatile / affidabile rispetto al solito equivalente:

for i in "$@"; do
  something with "$i"
done

per cui la shell Bourne, ksh88 presenta alcuni problemi in alcune condizioni (come quando $#è 0 in alcune versioni della shell Bourne (che ${1+"$@"}invece di "$@"può aggirare) o quando $IFSnon contiene il carattere spaziale in Bourne e ksh88), o quando l' nounsetopzione è abilitata ed $#è 0 in alcune versioni di alcune shell tra cui bash(di nuovo con ${1+"$@"}una soluzione ).


Ho dovuto leggere questo tre volte prima che il mio cervello decidesse di smettere di ripetere il "loop" ripetuto all'inizio
Three Diag

20

Questo è il comportamento predefinito, sì. E 'documentato nel helpdella forparola chiave:

terdon@tpad ~ $ help for
for: for NAME [in WORDS ... ] ; do COMMANDS; done
    Execute commands for each member in a list.

    The `for' loop executes a sequence of commands for each member in a
    list of items.  If `in WORDS ...;' is not present, then `in "$@"' is
    assumed.  For each element in WORDS, NAME is set to that element, and
    the COMMANDS are executed.

    Exit Status:
    Returns the status of the last command executed.

Così, quando non si dà una lista per scorrere, questo verrà impostato a iterare su $@, la matrice di parametri posizionali ( a, be cnel tuo esempio).

E questo comportamento è definito da POSIX, quindi sì, è considerato "buona pratica" fino a quel punto.

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.