Чому ви не можете змінити порядок оператора переадресації входу протягом циклів?


11

У Bash ви можете перемістити операторів переадресації вводу на передню частину команди:

cat <<< "hello"
# equivalent to
<<< "hello" cat

Чому ви не можете зробити те ж саме протягом циклів?

while read -r line; do echo "$line"; done <<< "hello"
# hello

<<< "hello" while read -r line; do echo "$line"; done
# -bash: syntax error near unexpected token `do'

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

Відповіді:


16

Це лише наслідок того, як визначено граматику. З специфікації граматики оболонки POSIX :

command          : simple_command
                 | compound_command
                 | compound_command redirect_list
                 | function_definition
                 ;

І:

simple_command   : cmd_prefix cmd_word cmd_suffix
                 | cmd_prefix cmd_word
                 | cmd_prefix
                 | cmd_name cmd_suffix
                 | cmd_name
                 ;
[...]
cmd_prefix       :            io_redirect
                 | cmd_prefix io_redirect
                 |            ASSIGNMENT_WORD
                 | cmd_prefix ASSIGNMENT_WORD
                 ;
cmd_suffix       :            io_redirect
                 | cmd_suffix io_redirect
                 |            WORD
                 | cmd_suffix WORD
                 ;

Як бачите, зі складеними командами переадресація дозволена лише після , але з простими командами вона дозволена і раніше. Отже, коли оболонка бачить <redirection> foo, fooтрактується як проста команда, а не складна команда і whileбільше не трактується як ключове слово:

$ < foo while
bash: while: command not found

Отже, doнесподіване, оскільки воно дозволено лише після певних ключових слів.

Отже, це стосується не лише whileциклів, а більшості способів налаштування складних команд за допомогою зарезервованих слів:

$ < foo {
bash: {: command not found
$ < foo if
bash: if: command not found
$ < foo for
bash: for: command not found

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