Bash "for" loop tanpa bagian "in foo bar ..."

25

Saya baru-baru ini melihat beberapa kode yang membingungkan saya karena berfungsi dan saya tidak mengharapkannya. Kode dikurangi menjadi contoh ini

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

Saat dijalankan dengan argumen baris perintah adalah mencetaknya

$ ./test a b c
a
b
c

Inilah ini, yang (bagi saya) tidak terduga. Mengapa ini tidak menghasilkan kesalahan karena vartidak terdefinisi? Apakah menggunakan ini dianggap sebagai 'praktik yang baik'?

pengguna270650
sumber

Jawaban:

27

forloop loop pada parameter posisi jika tidak ada in value1 value2...bagian yang ditentukan dalam semua shell Bourne-like.

Itu sudah menjadi kasus di shell Bourne dari akhir 70-an, meskipun dalam shell Bourne, Anda harus menghilangkan itu ;(Anda juga dapat menggunakan for i do(kecuali dalam beberapa versi abu lama di mana Anda memerlukan baris baru sebelum do)).

Lihat Apa tujuan kata kunci "lakukan" di Bash untuk loop? untuk informasi lebih lanjut termasuk varian yang lebih mengejutkan .

Perbuatan:

for i
do
  something with "$i"
done

adalah praktik yang baik. Ini sedikit lebih portabel / dapat diandalkan daripada yang biasanya setara:

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

di mana shell Bourne, ksh88 memiliki beberapa masalah di bawah beberapa kondisi (seperti kapan $#0 di beberapa versi shell Bourne (yang ${1+"$@"}alih-alih "$@"dapat bekerja di sekitar) atau ketika $IFStidak mengandung karakter spasi di Bourne dan ksh88), atau ketika yang nounsetpilihan ini diaktifkan dan $#0 dalam beberapa versi beberapa kerang termasuk bash( lagi dengan ${1+"$@"}sebagai kerja-sekitar ).

Stéphane Chazelas
sumber
Harus membaca ini tiga kali sebelum otak saya memutuskan untuk berhenti mengedit 'lingkaran' yang diulang di awal
Three Diag
20

Ini adalah perilaku default, ya. Hal ini didokumentasikan dalam helpdari forkata kunci:

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.

Jadi, ketika Anda tidak memberikan daftar untuk beralih lagi, itu akan default untuk beralih lagi, $@array parameter posisi ( a, bdan cdalam contoh Anda).

Dan perilaku ini didefinisikan oleh POSIX jadi ya, itu dianggap "praktik yang baik" sejauh itu.

terdon
sumber