Как удалить символ новой строки в конце файла?

35

Позвольте мне прояснить характер новой строки:

$ echo Hello > file1 ; cat file1
Hello
$ echo -n  Hello > file2 ; cat file2
Hello$ 

Здесь вы можете увидеть, что file1в конце file2есть символ новой строки, а не имеет.

Теперь предположим, что я один file:

$ cat file
Hello
Welcome to
Unix
$

И я хочу добавить and Linuxв конце файла, а затем echo " and Linux" >> fileбудет добавлен в новую строку . Но я хочу, чтобы последняя строкаUnix and Linux

Итак, чтобы обойти, я хочу удалить символ новой строки в конце файла. Следовательно, как мне удалить символ новой строки в конце файла?

Pandya
источник
6
Не удаляйте его, просто используйте текстовый редактор. sed '$s/$/ and linux/'
123

Ответы:

29

Если все, что вы хотите сделать, это добавить текст в последнюю строку, это очень просто с помощью sed. Замените $(сопоставление с образцом в конце строки) текстом, который вы хотите добавить, только в строках диапазона $(что означает последнюю строку).

sed '$ s/$/ and Linux/' <file >file.new &&
mv file.new file

который в Linux может быть сокращен до

sed -i '$ s/$/ and Linux/' file

Если вы хотите удалить последний байт в файле, Linux (точнее, GNU coreutils) предлагает truncateкоманду, которая делает это очень просто.

truncate -s -1 file

POSIX способ сделать это с dd. Сначала определите длину файла, а затем обрежьте его до одного байта меньше.

length=$(wc -c <file)
dd if=/dev/null of=file obs="$((length-1))" seek=1

Обратите внимание, что оба они безусловно обрезают последний байт файла. Вы можете сначала проверить, что это новая строка:

length=$(wc -c <file)
if [ "$length" -ne 0 ] && [ -z "$(tail -c -1 <file)" ]; then
  # The file ends with a newline or null
  dd if=/dev/null of=file obs="$((length-1))" seek=1
fi
Жиль "ТАК - перестань быть злым"
источник
9
Гораздо лучше способ удалить символ новой строки является perl -pi -e 'chomp if eof' myfile. По сравнению с truncateили ddэто не оставит вас с испорченным файлом, если на myfileсамом деле не было завершающих строк.
Привет-ангел
2
@ Привет-ангел. Могу ли я рекомендовать написать это в качестве ответа? Я думаю, что это был бы очень хороший ответ.
Саймон Форсберг
@SimonForsberg спасибо, готово .
Привет, Ангел,
17

Тем не менее, вы можете удалить символ новой строки из строки tr -d '\n':

$ echo -e "Hello"
Hello
$ echo -e "Hello" | tr -d '\n'
Hello$

Вы можете удалить символ новой строки в конце файла следующим простым способом:

  1. head -c -1 file

    От man head:

    -c, --bytes=[-]K
              print the first K bytes of each file; with the leading '-',
              print all but the last K bytes of each file
  2. truncate -s -1 file

    от man truncate:

    -s, --size=SIZE
              set or adjust the file size by SIZE

    SIZE is an integer and optional unit (example: 10M is 10*1024*1024).
    Units are K, M, G, T, P, E, Z, Y (powers of 1024) or KB, MB, ... (powers of 1000).
    
    SIZE  may  also be prefixed by one of the following modifying characters: 
    '+' extend by, '-' reduce by, '<' at most, '>' at least, '/' round down to multiple of, '%' round up to multiple of.
Pandya
источник
это head -c -1 file | tee fileбезопасно? Не teeобрезать файл перед запуском?
iruvar
1
@ 1_CR Действительно. Две стороны трубы начинаются параллельно, вопрос в том, кто выиграет гонку. Поскольку teeнужно только открыть файл, а headчитать и записать его содержимое, teeна практике выиграет гонку, за исключением иногда очень маленьких файлов.
Жиль "ТАК - перестань быть злым"
2
Это не удаляет последний перевод строки, он удаляет все переводы строки. ИМО довольно большая разница.
Привет-ангел
10

Вы можете достичь этого с помощью Perl как:

perl -pi -e 'chomp if eof' myfile

По сравнению с truncateили ddэто не оставит вас с испорченным файлом, если на myfileсамом деле не было завершающих строк.

(ответ построен на основе комментария и основан на этом ответе )

Привет, ангел
источник
Спасибо! Этот условный метод удаления новой строки идеален.
xer0x
3

Вот один из способов sed- в последней ( $) строке файла выполнить поиск и заменить что угодно и все ( .*) на «все, что вы сопоставили», а затем «и Linux»:

sed '$s/\(.*\)/\1 and Linux/' file

Еще более простое решение, предоставленное Исааком :

sed '$s/$/ and Linux/' file

Это заменяет (символический) конец строки заданным текстом.

Джефф Шаллер
источник
Айзек, мне нравится это предложение! Это проще / более очевидно. Я обновлю ответ с этим. Спасибо!
Джефф Шаллер