читайте-a выстраивают-d '\n' <нечто, код выхода 1

Параметр и другие типы расширений выполняются, когда команда читается, прежде чем это будет выполнено.

Первая версия, 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-м веке.

8
19.06.2013, 23:25
2 ответа

Что потребности быть объясненным то, что команда, казалось, работала, не ее код выхода

'\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 не исключение. Вот пара:

  1. Если Вы не указываете -r, read интерпретирует escape-последовательности обратной косой черты. Если это не на самом деле, что Вы хотите (который это иногда, но только иногда), необходимо не забыть указывать -r чтобы не иметь символы исчезают в редком случае, что существуют обратные косые черты во входе.

  2. Факт это read возвращается код выхода 1 не означает, что перестал работать. Это, возможно, успешно выполнилось, за исключением нахождения разделителя строки. Так будьте осторожны с циклом как это: while read -r LINE; do something with LINE; done потому что это не do something с последней строкой в редком случае, что последняя строка не имеет новой строки в конце.

  3. read -r LINE сохраняет обратные косые черты, но это не сохраняет ведущий или запаздывающий пробел.

14
27.01.2020, 20:09
  • 1
    Спасибо! я Думал, что попробовал $ '\n' подход, но я предполагаю не:/хороший знать о-r, хотя –  RasmusWL 20.06.2013, 01:33
  • 2
    "редкий случай, что последняя строка не имела новой строки", кажется, мне не неопровержимый довод для уведомления "никогда использованию while read". Иначе, фантастический ответ. –  glenn jackman 20.06.2013, 02:21
  • 3
    @glennjackman: можно использовать while read пока у Вас ничего нет в цикле. Иначе это - ошибка, ожидающая, чтобы укусить Вас - и верить мне, я был укушен. программное обеспечение –  rici 20.06.2013, 02:32
  • 4
    , последняя строка всегда имеет новую строку. Это - то, как определяется строка: это заканчивается новой строкой. Если непустой файл не заканчивается новой строкой, это не текстовый файл, и Вы не можете использовать инструменты обработки текста, такие как утилита оболочки read. –  Gilles 'SO- stop being evil' 20.06.2013, 02:50
  • 5
    @glennjackman: Меня, я выполняю итерации через columnised файлы с awk, главным образом. Для итерации целых строк, где файл не является слишком большим, mapfile довольно прохладно. Для взлома quick&dirty я буду использовать запрещенный цикл с условием продолжения, но я прекратил помещать это в производственные сценарии. YMMV и я смягчили предупреждение в ответе. –  rici 20.06.2013, 03:10

Это - ожидаемое поведение:

Код возврата является нулем, если с концом файла не встречаются, [...]

start cmd:> echo a b c | { read -a testarray; echo $?; }
0

start cmd:> echo -n a b c | { read -a testarray; echo $?; }
1
4
27.01.2020, 20:09

Теги

Похожие вопросы