Как удалить EOF пустую строку созданную sed
Я использую sed, чтобы изменить первую часть текстового файла. Проблема в том, что sed автоматически вводит пустую строку в конце файла.
Вы знаете, как это решить? (Не использовать усечение, так как я не хочу устанавливать дополнительное программное обеспечение в MacOS)
Спасибо!!
1 ответ
Быстрый ответ на ваш вопрос состоял бы в том, чтобы перенаправить вывод на другой cmd awk
:
sed 'commands' file | awk '(NR>1){printf "%s\n",l}{l=$0}END{printf "%s",l}'
Это удалит последний <newline>
, Это не может быть сделано sed
, ответ ниже пытается объяснить это. Дополнительные возможности можно найти в разделе Как удалить новую строку, если это последний символ в файле?
Почему sed
всегда заканчивается <newline>
? Ответ на этот вопрос зависит от толкования стандарта и реализации sed
ты используешь.
Согласно sed
стандарт posix:
В операции по умолчанию,
sed
циклически должен добавлять строку ввода, за вычетом ее окончания<newline>
характер, в пространство образца. Чтение с ввода должно быть пропущено, если<newline>
был в шаблонном пространстве доD
Команда, заканчивающая предыдущий цикл. Затем утилита sed последовательно применяет все команды, адреса которых выбирают это пространство шаблона, до тех пор, пока команда не начнет следующий цикл или не завершит работу. Если никакие команды явно не запускали новый цикл, то в конце сценария пространство шаблона должно быть скопировано в стандартный вывод (кроме случаев, когда-n
указано), и пространство шаблона должно быть удалено. Всякий раз, когда пространство шаблона записывается в стандартный вывод или именованный файл,sed
должен немедленно следовать за ним с<newline>
,
Это означает две вещи:
- строка не обрабатывается, если она не завершена
<newline>
, - все, что записано в стандартный вывод, заканчивается
<newline>
т.е. вывод в результате окончания командного цикла или выдачи командp
или жеP
,
Пример: sed (SunOS 5.10) SUNWcsu 11.10.0 rev=2005.01.21.15.53
$ echo -n foo | sed 'p'
$ echo -n 'foo\nbar' | sed 'p'
foo
foo
Там явно нет обработки, если строки, которые не завершены <newline>
, Иначе <newlines>
добавляются на любом выходе.
MacOS sed
Руководство имеет аналогичную интерпретацию как posix.
Обычно,
sed
циклически копирует строку ввода, не включая ее завершающий символ новой строки, в пространство шаблона (если после чего-то не осталосьD
function), применяет все команды с адресами, которые выбирают это пространство шаблона, копирует пространство шаблона в стандартный вывод, добавляет добавление новой строки и удаляет пространство шаблона.
Это не проверено, так как у меня нет Mac.
GNU sed
Руководство, похоже, имеет несколько иную точку зрения по этому вопросу:
sed
работает, выполняя следующий цикл для каждой строки ввода: во-первых, sed читает одну строку из входного потока, удаляет все завершающие символы новой строки и помещает ее в пространство шаблона. Затем команды выполняются; с каждой командой может быть связан адрес: адреса являются своего рода кодом условия, и команда выполняется только в том случае, если условие проверено перед выполнением команды.Когда достигнут конец сценария, если только
-n
опция используется, содержимое пространства шаблона распечатывается в выходной поток, добавляя обратно завершающий символ новой строки, если он был удален.
Что подразумевает следующее:
- все строки обработаны, все или не завершены
<newline>
- если достигнут конец командного цикла, то же количество
<newline>
's добавлено как было первоначально удалено.
Пример: sed (GNU sed) 4.2.2
В следующем примере символ новой строки добавляется только после p
а не после окончания цикла. (новая строка 012
в шестнадцатеричном)
$ echo -n foo | hexdump -b
0000000 146 157 157
0000003
$ echo -n foo | sed --posix 'p' | hexdump -b
0000000 146 157 157 012 146 157 157
0000007
Это объясняется сноской 7:
На самом деле, если
sed
печатает строку без завершающей новой строки, тем не менее, она будет печатать пропущенную новую строку, как только больше текста будет отправлено в тот же поток вывода, что дает "наименьший ожидаемый сюрприз", даже если он не выполняет такие команды, какsed -n p
точно такой же, какcat
,
В заключение: в соответствии со стандартом posix у вас всегда будет выходной файл, заканчивающийся <newline>
однако это может быть не последняя строка ввода. Согласно руководству по Gnu, ваш вывод заканчивается с тем же количеством, что и у вас в конце вашего входного файла.
Вопрос: это GNU sed --posix
настоящий посикс?