Как удалить 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 настоящий посикс?

Другие вопросы по тегам