Как я могу удалить новую строку, если это последний символ в файле?

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

0013600   n   t  >  \n

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

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

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

147
задан codeforester 4 March 2017 в 06:26
поделиться

8 ответов

perl -pe 'chomp if eof' filename >filename2

или, чтобы отредактировать файл на месте:

perl -pi -e 'chomp if eof' filename

[Примечание редактора: -pi -e изначально было -pie , но, как отметили несколько комментаторов и объяснил @hvd, последний не работает .]

Это было описано как «богохульство на perl» на веб-сайте awk, который я видел.

Но в тесте это сработало.

212
ответ дан 23 November 2019 в 21:59
поделиться

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

0
ответ дан 23 November 2019 в 21:59
поделиться
$  perl -e 'local $/; $_ = <>; s/\n$//; print' a-text-file.txt

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

3
ответ дан 23 November 2019 в 21:59
поделиться

Еще один Perl WTDI:

perl -i -p0777we's/\n\z//' filename
4
ответ дан 23 November 2019 в 21:59
поделиться

Вот красивое и аккуратное решение Python. Я не пытался быть здесь кратким.

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

Он обрезает файл на два байта, если последние два байта - CR / LF, или на один байт, если последний байт - LF. Он не пытается изменить файл, если последний байт (ы) не (CR) LF. Он обрабатывает ошибки. Протестировано на Python 2.6.

Поместите это в файл с именем striplast и chmod + x striplast .

#!/usr/bin/python

# strip newline from last line of a file


import sys

def trunc(filename, new_len):
    try:
        # open with mode "append" so we have permission to modify
        # cannot open with mode "write" because that clobbers the file!
        f = open(filename, "ab")
        f.truncate(new_len)
        f.close()
    except IOError:
        print "cannot write to file:", filename
        sys.exit(2)

# get input argument
if len(sys.argv) == 2:
    filename = sys.argv[1]
else:
    filename = "--help"  # wrong number of arguments so print help

if filename == "--help" or filename == "-h" or filename == "/?":
    print "Usage: %s <filename>" % sys.argv[0]
    print "Strips a newline off the last line of a file."
    sys.exit(1)


try:
    # must have mode "b" (binary) to allow f.seek() with negative offset
    f = open(filename, "rb")
except IOError:
    print "file does not exist:", filename
    sys.exit(2)


SEEK_EOF = 2
f.seek(-2, SEEK_EOF)  # seek to two bytes before end of file

end_pos = f.tell()

line = f.read()
f.close()

if line.endswith("\r\n"):
    trunc(filename, end_pos)
elif line.endswith("\n"):
    trunc(filename, end_pos + 1)

PS В духе Perl golf, вот мое кратчайшее решение Python. Он переносит весь файл со стандартного ввода в память, удаляет все символы новой строки с конца, и записывает результат в стандартный вывод. Не такой краткий, как Perl; вы просто не сможете превзойти Perl в таких маленьких сложных быстрых вещах, как этот.

Удалите "\ n" из вызова .rstrip () , и он удалит все пробелы в конце файл, включая несколько пустых строк.

Поместите это в "slurp_and_chomp.py", а затем запустите python slurp_and_chomp.py outputfile .

import sys

sys.stdout.write(sys.stdin.read().rstrip("\n"))
5
ответ дан 23 November 2019 в 21:59
поделиться

gawk

   awk '{q=p;p=$0}NR>1{print q}END{ORS = ""; print p}' file
10
ответ дан 23 November 2019 в 21:59
поделиться

Если вы хотите сделать это правильно, вам понадобится что-то вроде этого:

use autodie qw(open sysseek sysread truncate);

my $file = shift;
open my $fh, '+>>', $file;
my $pos = tell $fh;
sysseek $fh, $pos - 1, 0;
sysread $fh, my $buf, 1 or die 'No data to read?';

if($buf eq "\n"){
    truncate $fh, $pos - 1;
}

Мы открываем файл для чтения и добавления; открытие для добавления означает, что мы уже ищем до конца файла. Затем мы получаем числовую позицию конца файла с помощью tell . Мы используем это число для поиска одного символа, а затем читаем этот символ. Если это новая строка, мы обрезаем файл до символа перед этой новой строкой, в противном случае мы ничего не делаем.

Это выполняется с постоянным временем и постоянным пространством для любого ввода и не требует больше места на диске.

8
ответ дан 23 November 2019 в 21:59
поделиться
head -n -1 abc > newfile
tail -n 1 abc | tr -d '\n' >> newfile

Редактировать 2:

Вот awk версия (исправлено) , которая не накапливает потенциально огромный массив:

awk '{if (line) print line; line = $ 0} END {printf $ 0} 'abc

16
ответ дан 23 November 2019 в 21:59
поделиться
Другие вопросы по тегам:

Похожие вопросы: