Удаление символа новой строки в конце файла

Чтобы удалить все новые строки, вы можете:

tr -d '\n' < days.txt
cat days.txt | tr -d '\n'

но как бы вы использовали tr для удаления только новой строки в конце/конце текстового файла?

Я не обязательно укажу только последний.

Ответы

Ответ 1

Воспользуйтесь тем, что a) символ новой строки находится в конце файла и b) символ имеет размер 1 байт: используйте команду truncate для сокращения файла на один байт:

# a file with the word "test" in it, with a newline at the end (5 characters total)
$ cat foo 
test

# a hex dump of foo shows the '\n' at the end (0a)
$ xxd -p foo
746573740a

# and `stat` tells us the size of the file: 5 bytes (one for each character)
$ stat -c '%s' foo
5

# so we can use `truncate` to set the file size to 4 bytes instead
$ truncate -s 4 foo

# which will remove the newline at the end
$ xxd -p foo
74657374
$ cat foo
test$ 

Вы также можете перевернуть размер и математику в одну строку:

truncate -s $(($(stat -c '%s' foo)-1)) foo

Ответ 2

Более простое решение, чем принятое:

truncate -s -1 <<file>>

На странице усеченного человека:

-s, --size=SIZE
    set or adjust the file size by SIZE
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.

Ответ 3

Если вы уверены, что последний символ является новой строкой, это очень просто:

head -c -1 days.txt

head -c -N означает все, кроме последних N байтов

Ответ 4

Я думаю, что ваш лучший выбор - Perl:

perl -0pe 's/\n\Z//' days.txt

-0 заставляет perl рассматривать весь файл как одну большую строку. -p говорит ему распечатать эту строку после запуска программы на ней. И -e говорит: "вот программа для запуска".

Регулярное выражение \n\Z соответствует новой строке, но только если это последний символ в строке. И s/\n\Z// говорит, что нужно заменить такой символ новой строки вообще ничего, удалив его.

Приведенная выше команда выводит новую версию файла, но вместо этого вы можете изменить существующую, добавив -i ("in -p lace"), опционально с суффиксом, который будет использоваться для именования резервной копии файл перед его изменением:

 perl -i.bak -0pe 's/\n\Z//' days.txt

Это решение безопасно в том, что если последний символ не является новой строкой, он не будет затронут. Другие решения, которые просто удаляют последний байт, независимо от того, что может повредить такой файл.

Ответ 5

Попробуйте выполнить следующую команду: sed '$ { /^$/ d}' days.txt

Вы можете прочитать это как: "проверить, является ли последняя строка пустой строкой, если это так удалить эту строку". Я тестировал в обоих случаях: сначала с файлом, имеющим новую строку в конце, а в другой раз с файлом, заканчивающимся чем-то другим.