Bash „for” loop bez części „in foo bar…”

25

Ostatnio patrzyłem na kod, który mnie pomylił, ponieważ działa, a nie spodziewałem się, że to zrobi. Kod ogranicza się do tego przykładu

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

Gdy jest uruchamiany z argumentami wiersza poleceń, drukuje je

$ ./test a b c
a
b
c

To jest (dla mnie) nieoczekiwane. Dlaczego nie powoduje to błędu, ponieważ varjest niezdefiniowany? Czy stosowanie tego jest uważane za „dobrą praktykę”?

użytkownik270650
źródło

Odpowiedzi:

27

forzapętla pętle na parametrach pozycyjnych, jeśli żadna in value1 value2...część nie jest określona we wszystkich powłokach podobnych do Bourne'a.

Tak było już w przypadku powłoki Bourne'a z późnych lat 70., chociaż w powłoce Bourne'a należałoby to pominąć ;(możesz także użyć for i do(z wyjątkiem niektórych starych wersji jesionowych, w których przed nową linią potrzebujesz do)).

Zobacz Jaki jest cel słowa kluczowego „do” w Bash dla pętli? aby uzyskać więcej informacji, w tym bardziej zaskakujące warianty.

Robić:

for i
do
  something with "$i"
done

jest dobrą praktyką. Jest nieco bardziej przenośny / niezawodny niż zwykle równoważny:

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

dla których powłoka Bourne'a, ksh88 ma pewne problemy pod pewnymi warunkami (np. kiedy $#jest 0 w niektórych wersjach powłoki Bourne'a (które ${1+"$@"}zamiast tego "$@"mogą działać) lub gdy $IFSnie zawiera znaku spacji w Bourne i ksh88), lub gdy nounsetopcja jest włączona i $#jest 0 w niektórych wersjach niektórych muszli oraz bash( ponownie ${1+"$@"}jako obejście ).

Stéphane Chazelas
źródło
Musiałem przeczytać to trzy razy, zanim mój mózg postanowił przestać edytować powtarzającą się „pętlę” na początku
Three Diag
20

To jest domyślne zachowanie, tak. Jest to udokumentowane w helptego forsłowa kluczowego:

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.

Tak więc, jeśli nie dać mu listę iteracyjne nad, to domyślnie iteracji nad $@tablica parametrów pozycyjnych ( a, ba cna swoim przykładzie).

To zachowanie jest zdefiniowane przez POSIX, więc tak, uważa się je za „dobrą praktykę”.

terdon
źródło