Почему `tail -n 1` возвращает две строки в этом файле, когда я ожидаю 1
Файл в этом списке содержит две длинные строки.
- Когда я бегу
tail -n 1
на нем возвращаются обе строки (я бы ожидал только последнюю). - Когда я бегу
head -n 1
на нем возвращается только первая строка (как и ожидалось). - Когда я бегу
wc -l
на нем он возвращает 1 (я бы ожидал 2).
Если я уберу один символ из первой или второй строки, то некоторые вещи изменятся:
- [РАЗНОЕ] Когда я бегу
tail -n 1
на нем возвращается только последняя строка (как и ожидалось). - [ЖЕ] Когда я бегу
head -n 1
на нем возвращается только первая строка (как и ожидалось). - [ЖЕ] Когда я бегу
wc -l
на нем он возвращает 1 (я бы ожидал 2).
Что здесь происходит? Почему tail
а также wc
не ведет себя так, как я ожидал от этого файла?
Я работаю на OSX 10.14.2, и коллега смог воспроизвести такое же поведение на другой машине.
1 ответ
После просмотра файла с помощью инструмента шестнадцатеричного дампа создается впечатление, что в конце файла нет новой строки. Интересно, что gnu coreutils справляется с этим, а bsd coreutils (входит в состав MacOS) - нет. Более подробную информацию можно найти в этой публикации.
Утилиты, которые должны работать с текстовыми файлами, могут плохо работать с файлами, которые не заканчиваются символом новой строки; например, исторические утилиты Unix могут игнорировать текст после последней новой строки. Утилиты GNU придерживаются политики приличного поведения с нетекстовыми файлами, как и большинство других современных утилит, но вы все равно можете столкнуться со странным поведением с файлами, в которых отсутствует финальный символ новой строки¹.
$ hexdump file-with-2-lines.txt
0000000 61 61 61 61 61 61 61 61 61 61 61 61 61 61 61 61
*
0001820 61 61 61 61 61 61 61 61 61 61 61 61 0a 62 62 62
0001830 62 62 62 62 62 62 62 62 62 62 62 62 62 62 62 62
*
0003000 62
0003001
После редактирования файла (без внесения изменений, просто с помощью редактора, который вводит новые строки в конце файла).
$ hexdump file-with-2-lines.txt
0000000 61 61 61 61 61 61 61 61 61 61 61 61 61 61 61 61
*
0001820 61 61 61 61 61 61 61 61 61 61 61 61 0a 62 62 62
0001830 62 62 62 62 62 62 62 62 62 62 62 62 62 62 62 62
*
0003000 62 0a
0003002
0a
символ новой строки.