Как я могу удалить новую строку, если это последний символ в файле? - PullRequest
146 голосов
/ 31 октября 2009

У меня есть несколько файлов, которые я хотел бы удалить последней новой строкой, если это последний символ в файле. od -c показывает, что команда, которую я запускаю, записывает файл с новой строкой:

0013600   n   t  >  \n

Я попробовал несколько трюков с sed, но лучшее, что я мог придумать, это не делать трюк:

sed -e '$s/\(.*\)\n$/\1/' abc

Есть идеи, как это сделать?

Ответы [ 22 ]

3 голосов
/ 31 октября 2009
$  perl -e 'local $/; $_ = <>; s/\n$//; print' a-text-file.txt

См. Также Соответствует любому символу (включая символы новой строки) в sed .

2 голосов
/ 22 марта 2013
perl -pi -e 's/\n$// if(eof)' your_file
2 голосов
/ 03 мая 2010

Предполагается, что тип файла Unix и вам нужен только последний перевод строки, это работает.

sed -e '${/^$/d}'

Он не будет работать на нескольких новых строках ...

* Работает, только если последняя строка является пустой строкой.

2 голосов
/ 03 мая 2010

Использование дд:

file='/path/to/file'
[[ "$(tail -c 1 "${file}" | tr -dc '\n' | wc -c)" -eq 1 ]] && \
    printf "" | dd  of="${file}" seek=$(($(stat -f "%z" "${file}") - 1)) bs=1 count=1
    #printf "" | dd  of="${file}" seek=$(($(wc -c < "${file}") - 1)) bs=1 count=1
1 голос
/ 11 апреля 2012

Еще один ответ FTR (и мой любимый!): Echo / cat - вещь, которую вы хотите раздеть и захватить вывод с помощью обратных токов. Последний перевод строки будет удален. Например:

# Sadly, outputs newline, and we have to feed the newline to sed to be portable
echo thingy | sed -e 's/thing/sill/'

# No newline! Happy.
out=`echo thingy | sed -e 's/thing/sill/'`
printf %s "$out"

# Similarly for files:
file=`cat file_ending_in_newline`
printf %s "$file" > file_no_newline
1 голос
/ 25 августа 2016

POSIX САС:

'$ {/ ^ $ / d}'

$ - match last line


{ COMMANDS } - A group of commands may be enclosed between { and } characters. This is particularly useful when you want a group of commands to be triggered by a single address (or address-range) match.
0 голосов
/ 28 августа 2018

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

# with trailing newline
echo -en 'foo\nbar\n' | sed '$s/$//' | head -c -1

# still works without trailing newline
echo -en 'foo\nbar' | sed '$s/$//' | head -c -1

# read from a file
sed '$s/$//' myfile.txt | head -c -1

подробности:

  • head -c -1 усекает последний символ строки, независимо от того, что это за символ. Поэтому, если строка не заканчивается новой строкой, вы потеряете символ.
  • Итак, чтобы решить эту проблему, мы добавим еще одну команду, которая добавит завершающий символ новой строки, если его нет: sed '$s/$//'. Первый $ означает только применить команду к последней строке. s/$// означает замену «конца строки» словом «ничего», которое в основном ничего не делает. Но у него есть побочный эффект добавления завершающего символа новой строки, если его нет.

Примечание. Mac по умолчанию head не поддерживает параметр -c. Вы можете сделать brew install coreutils и использовать ghead вместо.

0 голосов
/ 01 ноября 2009

Единственный раз, когда я хотел сделать это для кода гольф, а затем я просто скопировал свой код из файла и вставил его в оператор echo -n 'content'>file.

0 голосов
/ 20 марта 2010
sed ':a;/^\n*$/{$d;N;};/\n$/ba' file
0 голосов
/ 18 мая 2016

рубин:

ruby -ne 'print $stdin.eof ? $_.strip : $_'

или

ruby -ane 'q=p;p=$_;puts q if $.>1;END{print p.strip!}'
...