Параметр и другие типы расширений выполняются, когда команда читается, прежде чем это будет выполнено.
Первая версия, LANG=Ja_JP bash -c "echo $LANG"
, единственная команда. После того, как это анализируется как таковое, $LANG
расширен до en_US
прежде чем что-либо будет выполнено. Однажды bash
закончен, обработав вход, он разветвляет процесс, добавляет LANG=Ja_JP
к среде как ожидалось, и затем выполняется bash -c echo en_US
.
Можно предотвратить расширение с одинарными кавычками, т.е. LANG=Ja_JP bash -c 'echo $LANG'
выводы Ja_JP
.
Обратите внимание, что, когда у Вас есть переменное присвоение как часть команды, присвоение только влияет на среду той команды и не той из Вашей оболочки.
Вторая версия, LANG=Ja_JP; bash -c "echo $LANG"
на самом деле две отдельных команды, выполняемые в последовательности. Первым является присвоение простой переменной без команды, таким образом, это влияет на Вашу текущую оболочку.
Таким образом Ваши два отрывка существенно отличаются несмотря на поверхностное различие сингла ;
.
Полностью вне темы, но мог бы я рекомендовать добавить a .UTF-8
при установке LANG
. Нет никакого серьезного основания в наше время для не использования Unicode в 21-м веке.
Что потребности быть объясненным то, что команда, казалось, работала, не ее код выхода
'\n'
два символа: обратная косая черта \и буква N. То, что Вы думали, что Вам было нужно, было $'\n'
, который является переводом строки (но это не было бы правильно также, посмотрите ниже).
-d
опция делает это:
-d delim continue until the first character of DELIM is read, rather than newline
Таким образом без той опции, read
читал бы до новой строки, разделил бы строку на слова с помощью символов в $IFS
как разделители, и помещенный слова в массив. Если Вы указали -d $'\n'
, устанавливая разделитель строки на новую строку, это сделало бы точно то же самое. Установка -d '\n'
средства, которые это считает до первой обратной косой черты (но, еще раз, видят ниже), который является первым символом в delim
. С тех пор нет никакой обратной косой черты в Вашем файле, read
завершится в конце файла, и:
Exit Status:
The return code is zero, unless end-of-file is encountered, read times out,
or an invalid file descriptor is supplied as the argument to -u.
Таким образом, вот почему код выхода равняется 1.
От того, что Вы полагаете, что команда работала, мы можем прийти к заключению, что нет никаких пробелов в файле, так, чтобы read
, после чтения всего файла в бесполезной надежде на нахождение обратной косой черты, разделит его пробелом (значение по умолчанию $IFS
), включая новые строки. Таким образом, каждая строка (или каждое слово, если строка содержит больше чем одно слово) спрятались в массив.
Таинственный случай присвоенной обратной косой черты
Теперь, как я знал, что файл не содержал обратных косых черт? Поскольку Вы не предоставляли -r
флаг к read
:
-r do not allow backslashes to escape any characters
Таким образом, если бы у Вас были какие-либо обратные косые черты в файле, они были бы разделены, если у Вас не было двух из них подряд. И, конечно, существует доказательство это read
имел код выхода 1, который демонстрирует, что не нашел обратную косую черту, таким образом, не было двух из них подряд также.
Еда на дом
Bash не был бы ударом, если бы не было глюков, скрывающихся позади примерно каждой команды, и read
не исключение. Вот пара:
Если Вы не указываете -r
, read
интерпретирует escape-последовательности обратной косой черты. Если это не на самом деле, что Вы хотите (который это иногда, но только иногда), необходимо не забыть указывать -r
чтобы не иметь символы исчезают в редком случае, что существуют обратные косые черты во входе.
Факт это read
возвращается код выхода 1 не означает, что перестал работать. Это, возможно, успешно выполнилось, за исключением нахождения разделителя строки. Так будьте осторожны с циклом как это: while read -r LINE; do something with LINE; done
потому что это не do something
с последней строкой в редком случае, что последняя строка не имеет новой строки в конце.
read -r LINE
сохраняет обратные косые черты, но это не сохраняет ведущий или запаздывающий пробел.
Это - ожидаемое поведение:
Код возврата является нулем, если с концом файла не встречаются, [...]
start cmd:> echo a b c | { read -a testarray; echo $?; }
0
start cmd:> echo -n a b c | { read -a testarray; echo $?; }
1
while read
". Иначе, фантастический ответ. – glenn jackman 20.06.2013, 02:21while read
пока у Вас ничего нет в цикле. Иначе это - ошибка, ожидающая, чтобы укусить Вас - и верить мне, я был укушен. программное обеспечение – rici 20.06.2013, 02:32read
. – Gilles 'SO- stop being evil' 20.06.2013, 02:50mapfile
довольно прохладно. Для взлома quick&dirty я буду использовать запрещенный цикл с условием продолжения, но я прекратил помещать это в производственные сценарии. YMMV и я смягчили предупреждение в ответе. – rici 20.06.2013, 03:10