Необходимо пояснить, что команда работала, а не код выхода
'\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, который показывает, что он не нашел обратной косой черты, поэтому не было и двух из них подряд.
Takeaways
Bash не был бы bash, если бы не каждая команда скрывалась за каждой командой, и не read
является исключением. Вот пара:
Если вы не укажете -r
, read
будет интерпретировать escape-последовательности обратной косой черты. Если это не то, что вы на самом деле хотите (что иногда и происходит, но только изредка), не забывайте указывать, -r
чтобы не допустить исчезновения символов в редком случае обратной косой черты на входе.
Тот факт, что read
возвращается код выхода 1, не означает, что это не удалось. Это вполне могло бы быть успешным, за исключением поиска конца строки. Так что будьте осторожны с таким циклом: while read -r LINE; do something with LINE; done
потому что он не сможет работать do something
с последней строкой в редком случае, когда последняя строка не имеет символа новой строки в конце.
read -r LINE
сохраняет обратную косую черту, но не сохраняет начальные или конечные пробелы.
while read
». В противном случае, фантастический ответ.while read
если у вас ничего нет внутри цикла. Иначе это ошибка, ждущая, чтобы укусить тебя - и поверь мне, я был укушен.read
.mapfile
это довольно круто. Для быстрого и грязного взлома я буду использовать запрещенный цикл while, но я перестал вставлять это в производственные скрипты. YMMV и я смягчили предупреждение в ответе.Это ожидаемое поведение:
источник