Bash цикл "for" без частини "в foo bar ..."


25

Нещодавно я дивився на якийсь код, який мене бентежив, бо він працює, і я цього не очікував. Код зводиться до цього прикладу

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

При запуску з командним рядком аргументи друкує їх

$ ./test a b c
a
b
c

Саме це, що (для мене) несподівано. Чому це не призводить до помилки, оскільки varвона не визначена? Чи вважається використання цього «доброю практикою»?

Відповіді:


27

forциклічні петлі на позиційних параметрах, якщо жодна in value1 value2...частина не вказана у всіх оболонках Борна.

Це вже було в оболонці Bourne з кінця 70-х, хоча в оболонці Bourne це потрібно буде опустити ;(ви також можете використовувати for i do(за винятком деяких старих версій попелу, де вам потрібен новий рядок до початку do)).

Дивіться, яка мета ключового слова "робити" в Bash для циклів? для отримання додаткової інформації, включаючи більше дивних варіантів.

Виконуємо:

for i
do
  something with "$i"
done

є гарною практикою. Це трохи більш портативний / надійний, ніж зазвичай еквівалент:

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

для яких оболонка Bourne, ksh88 має деякі проблеми за певних умов (наприклад, коли $#в деяких версіях оболонки Bourne дорівнює 0 (або ${1+"$@"}замість того, що "$@"може $IFSобійтися) або коли не містить символу пробілу в Bourne та ksh88), або коли nounsetопція включена , і $#0 в деяких версіях деяких оболонок , включаючи bash( знову ${1+"$@"}як обхідний ).


Довелося прочитати це тричі, перш ніж мій мозок вирішив припинити редагування повторного "циклу" на початку
Three Diag

20

Це поведінка за замовчуванням, так. Документально в helpз forключового слова:

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.

Так що , якщо ви не даєте йому список перебрати, він буде по замовчуванням ітерації $@, масив позиційних параметрів ( a, bі cв вашому прикладі).

І така поведінка визначена POSIX, так що так, це вважається "хорошою практикою", наскільки це стосується.

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.