2013-11-23 1 views
32

Я смущен о том, что коде ошибки команда возвращает при выполнении назначения переменного явно и с командой подстановкой:Bash: код выхода переменного присвоения команды подстановки

a=$(false); echo $? 

Он выводит 1, которые позволяют мне думать это присвоение переменной не подметает или не создает новый код ошибки на последнем. Но когда я попытался это:

false; a=""; echo $? 

Он выводит 0, очевидно, это то, что a="" возвращается и переопределить 1 возвращаемый false.

Я хочу знать, почему это происходит, есть ли какая-либо особенность в присвоении переменной, отличная от других обычных команд? Или просто быть причиной a=$(false) считается одной командой, и только часть замещения команды имеет смысл?

- ОБНОВЛЕНИЕ -

Спасибо всем, от ответов и комментариев, которые я получил точку «Когда вы назначаете переменную с помощью подстановки команды, статус выхода является статус команды» (by @Barmar), это объяснение превосходно понятно и легко понять, но говорить недостаточно точно для программистов, я хочу видеть ссылку на этот вопрос у таких органов, как TLDP или справочная страница GNU, пожалуйста, помогите мне найти ее снова, спасибо!

+0

TLDP не является авторитетным источником - ABS является откровенным позорным для демонстрации плохих практик в bash, так же как w3schools находится в мире JavaScript. –

ответ

44

Выполнение команды $(command) позволяет использовать output of the command to replace itself.

Когда вы говорите:

a=$(false)    # false fails; the output of false is stored in the variable a 

вывод, генерируемый командой false хранится в переменной a. Кроме того, код выхода такой же, как и команда. help false бы сказать:

false: false 
    Return an unsuccessful result. 

    Exit Status: 
    Always fails. 

С другой стороны, говоря:

$ false    # Exit code: 1 
$ a=""     # Exit code: 0 
$ echo $?    # Prints 0 

вызывает код выхода для присвоения a быть возвращен, который 0.


EDIT:

Цитируя manual:

Если один из расширений содержит подстановку команд, статус команды выхода является статус выхода последней команды замена выполнена.

Цитируя BASHFAQ/002:

Как я могу сохранить возвращаемое значение и/или вывода команды в переменной?

...

output=$(command)

status=$?

Присваивание output не оказывает влияния на состояние выхода command «s, который все еще находится в $?.

+0

Очень хороший ответ :)! Можете ли вы, пожалуйста, помочь мне найти ссылку на «код выхода, тот же, что и в команде», я трачу много времени, но не получил результат :( – Reorx

+0

@Reorx Добавил пару ссылок в вышеизложенное – devnull

+0

Спасибо, это достаточно ясно: D – Reorx

0

(не ответ на оригинальный вопрос, но слишком долго для комментариев)

Обратите внимание, что export A=$(false); echo $? выходов 0! По-видимому, правила, приведенные в devnull's answer, больше не применяются. Для того, чтобы добавить немного контекста в этой цитате (курсив мой):

3.7.1 Простая команда расширения

...

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

3.7.2 Команда Поиск и выполнение [- это "ниже" случай]

IIUC руководство описывает var=foo, как частный случай var=foo command... синтаксиса (довольно запутанным!). Правило «exit status of last command substitution» применяется только к случаю без команд.

В то время как заманчиво думать о export var=foo как о «модифицированном синтаксисе присваивания», это не так: export - встроенная команда (которая просто принимает атрибуты, подобные присваиванию).

=> Если вы хотите экспортировать статус команды замещения уаг и захвата, сделайте это в 2 этапа:

A=$(false) 
# ... check $? 
export A 

Этот способ также работает в режиме set -e - выход немедленно, если замена команды возврата не-0 ,