Странный вывод из bash одним вкладышем

В процессе изучения bash я часто настраиваю существующую вещь и вижу ее вывод.

~$ for i in {1..19}; do echo "Everything in UNIX is a file."; sleep 1; done

У меня было это, и из любопытства я подправил вышеизложенное в следующее:

~$ for i in {1..19 * 2}; do echo "Everything in UNIX is a file."; echo "The value of i is ${i}";  sleep 1; done

Теперь, к моему удивлению, я начал получать следующий вывод:

Everything in UNIX is a file.
The value of i is OneDrive
Everything in UNIX is a file.
The value of i is opera autoupdate
Everything in UNIX is a file.
The value of i is Personal_Workspace
Everything in UNIX is a file.
The value of i is Pictures
Everything in UNIX is a file.
The value of i is PrintHood
Everything in UNIX is a file.
The value of i is Recent
Everything in UNIX is a file.
The value of i is Roaming
Everything in UNIX is a file.
The value of i is Saved Games
Everything in UNIX is a file.
The value of i is Searches

Некоторые из значений i - это имена файлов и каталогов в моем домашнем каталоге, я нахожусь в домашнем каталоге при выполнении этого скрипта.

То, что я ожидал, что значения i будут в диапазоне от 1 до 19*2 = 38, поэтому я буду принимать значения от 1,2,3...30...38. Но, очевидно, это не почему?

2 ответа

Решение

Да в bashРасширение диапазона происходит раньше всего остального. Вы ожидали, что произойдет арифметическое расширение, которое не произошло ожидаемым из-за порядка расширения bash ракушка. Ваш код закончил интерпретацию {1..19, * а также 2} как буквальные строки.

поскольку * имеет особое значение в оболочке, которая представляет собой глобальное расширение, в котором перечислены все файлы / каталоги в текущей папке. Также вы можете увидеть одну запись с указанием двух других строк, интерпретированных буквально.

Со страницы man bash(1) в разделе Expansion

Порядок расширений: расширение фигурных скобок, расширение тильды, расширение параметров, переменных и арифметики и подстановка команд (выполняется слева направо), разбиение слов и расширение имени пути.

Вы намного лучше, используя for петля с ((..)) построить, если вы нацелены на сценарии для Bourne снова оболочки

for ((i=1; i<=38; i++)); do

* Символ в оболочке Unix переводится в подстановочный знак, так что в основном то, что {1..19 * 2} означает от 1 до 19, все файлы в текущем каталоге (это *), а затем 2. это будут значения i в вашем цикле

Другие вопросы по тегам