1

Может кто-нибудь, пожалуйста, объясните мне это:

$ type blah
bash: type: blah: not found
$ echo $?
1

$ bash --init-file <( echo "type blah; echo $?" )
bash: type: blah: not found
0

Почему возвращаемое значение отличается в сценарии инициализации от интерактивной оболочки?

Изменить И снова в сценарии инициализации для интерактивной оболочки:

$ bash --init-file <( echo "type blah; echo $?" ) -i
bash: type: blah: not found
2

Версия Bash - 4.4.12.

2 ответа2

1

Ответь первым

  1. Init-скрипт не имеет ничего общего с возвращаемым значением.
  2. Подстановка процесса <(...) является реальной причиной.

объяснение

[Доказательство1] Теперь попробуйте эту команду ниже. У него нет опции --init-file , но тот же вывод (с некоторыми тривиальными отпечатками).

(exit 10)
bash <( echo "type blah; echo $?" )

[Proof2] Попробуйте следующие команды и измените число в первой, вы найдете более другое возвращаемое значение.

(exit 117)
bash --init-file <( echo "type blah; echo $?" )

[Proof3] Какой вывод вы видите?

(exit 23)
cat <( echo "type blah; echo $?" )

Я думаю, что вы можете понять ответ 1 через 3 доказательства выше. А как насчет Answer2?

Если вы просто наберете простую команду echo "type blah; echo $?" запустить его, какой результат вы ожидаете? Вы ожидаете, что это напечатает type blah; echo <num> , из которых <num> - это возвращаемое значение последней команды. Правильно? Мы все знаем $? будет заменено на число, потому что мы все знаем, что bash будет выполнять расширение параметров для $? ,

То же самое в подстановке процесса <(...) .

В Bash команды, которые появляются в подстановке процесса <(...) будут вызываться в подоболочке. Subshell также является оболочкой (Bash). Так что для команды echo "type blah; echo $?" вы получите точно такой же результат в subshell, как и при простом запуске в текущей оболочке, что означает, что subshell также выполнит расширение параметров в $? же, как в bash.

Итак, когда вы запускаете bash --init-file <(echo "type blah; echo $?") содержимое файла init-script на самом деле имеет type blah; echo <num> а не type blah; echo $?

Глубже

Хотя в процессе подстановки <(echo "type blah; echo $?") $? раскрывается подоболочкой, его значение зависит от текущей оболочки. Значение ? в subshell такой же, как в текущей оболочке.

Посмотрите Proof2, первая команда (exit 117) , которая делает значение $? в текущей оболочке будет 117. Но он также расширен до 117 в подоболочке.

Это связано с тем, что команды, появляющиеся в подстановке процесса <(...) , вызываются в среде подоболочки, которая является дубликатом текущей среды оболочки.

Таким образом, это объясняет, что в вашем вопросе вы указали другое возвращаемое значение, если в команде указали опцию -i . Это не разница, внесенная опцией -i . Это потому, что перед этой командой вы определенно выполняете другую команду, которая возвращает 2.

Больше слов

На самом деле, есть три другие формы, работающие так же, как подстановка процессов в bash.

  1. Подстановка команд $(...) или `...`
  2. Команды, сгруппированные в скобках (...)
  3. Встроенные команды в конвейере <builtin cmd> | ... или ... | <builtin cmd> или <builtin cmd> | <builtin cmd>
1

Проблема в том, что $? оценивается перед передачей в качестве аргумента внешней команде echo . В результате вы используете эквивалент:

bash --init-file <( echo "type blah; echo 0" ) -i

Вы можете увидеть это, используя режим set -x который покажет эквивалент выполненных команд:

$ bash --init-file <( echo "type blah; echo $?" )
+ bash --init-file /dev/fd/63
++ echo 'type blah; echo 0'
bash: type: blah: not found
0

Обратите внимание на третью строку, ++ echo 'type blah; echo 0' - $? уже был раскрыт до того, как он был передан команде echo (и, следовательно, новой оболочке для выполнения). Кстати, это означает, что на самом деле он показывает результат последней команды, выполненной перед этой:

$ curl http://notarealdomain.example.com/
curl: (6) Could not resolve host: notarealdomain.example.com
$ bash --init-file <( echo "type blah; echo $?" )
bash: type: blah: not found
6

Обратите внимание, что напечатанное состояние "6" является кодом curl для неразрешимой ошибки хоста.

В любом случае, решение простое: используйте одинарные кавычки, чтобы отложить оценку $?:

$ bash --init-file <( echo 'type blah; echo $?' )
bash: type: blah: not found
1

Всё ещё ищете ответ? Посмотрите другие вопросы с метками .