У меня есть несколько файлов, которые я хотел бы удалить последним символом новой строки, если это последний символ в файле. od -c
показывает, что команда, которую я запускаю, записывает файл с новой строкой:
0013600 n t > \n
Я попробовал несколько трюков с sed, но лучшее, что я мог придумать, это не делать трюк:
sed -e '$s/\(.*\)\n$/\1/' abc
Есть идеи как это сделать?
\n
, в Linux это один символОтветы:
или, чтобы отредактировать файл на месте:
[Примечание редактора:
-pi -e
изначально было-pie
, но, как отметили несколько комментаторов и объяснили @hvd, последнее не работает.]На веб-сайте awk это было описано как «богохульство на Perl».
Но в тесте это сработало.
источник
chomp
. И это лучше, чем хлебать файл.perl -pi -e 'chomp if eof' filename
, чтобы редактировать файл на месте вместо создания временного файлаperl -pie 'chomp if eof' filename
-> Не могу открыть Perl-скрипт "chomp if eof": такого файла или каталога нет;perl -pi -e 'chomp if eof' filename
-> работаетВы можете воспользоваться тем, что подстановки команд оболочки удаляют завершающие символы новой строки :
Простая форма, которая работает в bash, ksh, zsh:
Портативная (POSIX-совместимая) альтернатива (чуть менее эффективная):
Примечание:
in.txt
концы с несколькими символами новой строки, подмена команда удаляет все из них - спасибо, @Sparhawk. (Он не удаляет пробельные символы, кроме завершающих символов новой строки.)printf %s
гарантирует, что новая строка не добавляется к выводу (это POSIX-совместимая альтернатива нестандартной версииecho -n
; см. http://pubs.opengroup.org/onlinepubs/009696799/utilities/echo.html и https: //unix.stackexchange. com / a / 65819 )Руководство к другим ответам :
Если Perl доступен, перейдите к принятому ответу - он прост и экономит память (не читает весь входной файл сразу).
В противном случае, считают ghostdog74 игровая Awk ответ - это неясный, но и эффективно использует память ; более читаемый эквивалент (POSIX-совместимый) является:
awk 'NR > 1 { print prev } { prev=$0 } END { ORS=""; print }' in.txt
END
блоке, где она печатается без запаздывания\n
из-за установки разделителя выходной записи (OFS
) в пустую строку.Если вам нужно подробное, но быстрое и надежное решение, которое действительно редактирует на месте (в отличие от создания временного файла, который затем заменяет оригинальный), рассмотрите скрипт Perl jrockway .
источник
Вы можете сделать это с помощью
head
GNU coreutils, он поддерживает аргументы, относящиеся к концу файла. Итак, чтобы прекратить использование последнего байта:Чтобы проверить окончание новой строки, вы можете использовать
tail
иwc
. В следующем примере результат сохраняется во временный файл, а затем перезаписывается оригинал:Вы также можете использовать
sponge
frommoreutils
для редактирования "на месте":Вы также можете сделать общую функцию многократного использования, вставив это в свой
.bashrc
файл:Обновить
Как отметил Карл Уилбур в комментариях и использовал в Sorentar's ответ ,
truncate --size=-1
может заменитьhead -c-1
и опоры в месте редактирования.источник
truncate --size=-1
вместо,head -c -1
поскольку он просто изменяет размер входного файла, а не читает во входном файле, записывает его в другой файл, а затем заменяет оригинал выходным файлом.head -c -1
последний символ будет удален независимо от того, является ли он новой строкой или нет, поэтому перед его удалением необходимо проверить, является ли последний символ новой строкой.Изменить 2:Вотawk
версия (исправленная) , которая не накапливает потенциально огромный массив:awk '{if (line) print line; line = $ 0} END {printf $ 0} 'abcисточник
awk
версию. Требуется два смещения (и другой тест), и я использовал только один. Тем не менее, вы можете использоватьprintf
вместоORS
.head -n -1 abc | cat <(tail -n 1 abc | tr -d '\n') | ...
простак
источник
awk '{ prev_line = line; line = $0; } NR > 1 { print prev_line; } END { ORS = ""; print line; }' file
это должно быть легче читать.awk 'NR>1 {print p} {p=$0} END {printf $0}' file
.printf
является аргумент формата . Таким образом, если во входном файле есть что-то, что можно интерпретировать как описатель формата%d
, вы получите ошибку. Исправление было бы изменить его наprintf "%s" $0
Очень простой метод для однострочных файлов, требующий эхо GNU от coreutils:
источник
\n
присутствует. Поскольку это преобразовано в новую линию.$(...)
, которые цитируются/bin/echo -n "$(cat infile)"
Кроме того, я не уверен, какой будет максимальный размерecho
или оболочка в версиях / дистрибутивах os / shell (я просто гуглил это, и это была кроличья нора), так что я не уверен, насколько переносимым (или быстродействующим) он будет для чего-либо, кроме небольших файлов - но для маленьких файлов - отлично.Если вы хотите сделать это правильно, вам нужно что-то вроде этого:
Открываем файл для чтения и добавления; открытие для добавления означает, что мы уже
seek
отредактированы до конца файла. Затем мы получаем числовую позицию конца файла с помощьюtell
. Мы используем это число для поиска одного символа, а затем читаем этот символ. Если это новая строка, мы усекаем файл до символа перед новой строкой, в противном случае мы ничего не делаем.Это выполняется в постоянном времени и постоянном пространстве для любого ввода и не требует больше дискового пространства.
источник
Вот хорошее, аккуратное решение Python. Я не пытался быть кратким здесь.
Это изменяет файл на месте, а не делает копию файла и удаляет новую строку из последней строки копии. Если файл большой, это будет намного быстрее, чем решение Perl, которое было выбрано в качестве лучшего ответа.
Он усекает файл на два байта, если последние два байта равны CR / LF, или на один байт, если последний байт равен LF. Он не пытается изменить файл, если последние байты не являются (CR) LF. Он обрабатывает ошибки. Проверено в Python 2.6.
Поместите это в файл с именем "striplast" и
chmod +x striplast
.PS В духе "Perl golf", вот мое самое короткое решение Python. Он отбирает весь файл из стандартного ввода в память, удаляет все переводы строк с конца и записывает результат в стандартный вывод. Не так кратко, как Perl; вы просто не можете победить Perl за такие хитрые быстрые вещи, как эта.
Удалите «\ n» из вызова
.rstrip()
и он уберет все пробелы в конце файла, включая несколько пустых строк.Поместите это в «slurp_and_chomp.py» и затем запустите
python slurp_and_chomp.py < inputfile > outputfile
.источник
Быстрое решение использует утилиту gnu
truncate
:Тест будет верным, если в файле есть завершающая новая строка.
Удаление выполняется очень быстро, действительно на месте, новый файл не требуется, и поиск также читает с конца только один байт (
tail -c1
).источник
[ -z $(tail -c1 filename) ] && truncate -s -1 filename
(также, в ответ на другой комментарий,truncate
команда не работает с stdin, требуется имя файла)Еще один Perl WTDI:
источник
Смотрите также Подберите любой символ (включая символы новой строки) в sed .
источник
tr -d '\n'
Используя дд:
источник
источник
g
или в круглых скобкахeof
:perl -pi -e 's/\n$// if eof' your_file
.Предполагая Unix тип файла, и вам нужен только последний перевод строки, это работает.
Это не будет работать на нескольких новых строках ...
* Работает, только если последняя строка является пустой строкой.
источник
sed
решение, которое работает даже дляЕще один ответ FTR (и мой любимый!): Echo / cat - вещь, которую вы хотите раздеть и захватить вывод с помощью обратных кавычек. Финальный перевод строки будет удален. Например:
источник
POSIX САС:
'$ {/ ^ $ / D}'
источник
echo -en 'a\nb\n' | sed '${/^$/d}'
ничего не удалит.echo -en 'a\nb\n\n' | sed '${/^$/d}'
удалит, так как вся последняя строка пуста.Это хорошее решение, если вам нужно работать с конвейерами / перенаправлениями вместо чтения / вывода из или в файл. Это работает с одной или несколькими строками. Это работает, есть ли завершающий перевод строки или нет.
Подробности:
head -c -1
усекает последний символ строки независимо от того, что это за символ. Так что если строка не заканчивается новой строкой, то вы потеряете символ.sed '$s/$//'
. Первое$
означает применить команду только к последней строке.s/$//
означает заменить «конец строки» на «ничего», что в основном ничего не делает. Но у него есть побочный эффект добавления завершающего символа новой строки, если его нет.Примечание. Mac по умолчанию
head
не поддерживает эту-c
опцию. Вы можете сделатьbrew install coreutils
и использоватьghead
вместо этого.источник
Единственный раз, когда я хотел сделать это для кода гольф, а затем я просто скопировал свой код из файла и вставил его в
echo -n 'content'>file
утверждение.источник
источник
У меня была похожая проблема, но я работал с файлом Windows, и мне нужно сохранить эти CRLF - мое решение для Linux:
источник
Следует удалить все последние вхождения \ n в файле. Не работает с огромным файлом (из-за ограничения буфера sed)
источник
Рубин:
или:
источник