Подтвердить что ты не робот

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

Скажем, у меня есть несколько произвольных многострочных текстовых файлов:

sometext
moretext
lastline

Как удалить только последний символ (e, а не новую строку или нуль) файла, не делая текстовый файл недействительным?

4b9b3361

Ответ 1

Более простой подход (выходы на stdout, не обновляет входной файл):

sed '$ s/.$//' somefile
  • $ - это Sed-адрес, который соответствует только последней строке ввода, что вызывает выполнение следующего вызова функции (s/.$//) только в последней строке.
  • s/.$// заменяет последний символ строки (в данном случае последней) пустой строкой; то есть эффективно удаляет последний char. (перед новой строкой) на линии.
    . соответствует любому символу в строке, а после него с $ привязывает соответствие к концу строки; обратите внимание, как использование $ в этом регулярном выражении концептуально связано, но технически отличается от предыдущего использования $ в качестве Sed-адреса.
  • Пример со входом stdin (предполагается Bash, Ksh или Zsh):

    $ sed '$ s/.$//' <<< $'line one\nline two'
    line one
    line tw
    

Также обновить файл ввода (не использовать, если входной файл является символической ссылкой):

sed -i '$ s/.$//' somefile

Примечание:
* В OSX вам нужно будет использовать -i '' вместо -i; для обзора подводных камней, связанных с -i, см. нижнюю часть моего ответа здесь.
* Если вам нужно обрабатывать очень большие входные файлы и/или производительность/использование диска, вы беспокоитесь, и вы используете утилиты GNU (Linux), см. отзыв о сотернаре.

Ответ 2

truncate

truncate -s-1 file

Удаляет один (-1) символ из конца того же файла. Точно, как >> будет добавляться в тот же файл.

Проблема с этим подходом заключается в том, что он не сохраняет конечную новую строку, если она существует.

Решение:

if     [ -n "$(tail -c1 file)" ]    # if the file has not a trailing new line.
then
       truncate -s-1 file           # remove one char as the question request.
else
       truncate -s-2 file           # remove the last two characters
       echo "" >> file              # add the trailing new line back
fi

Это работает, потому что tail принимает последний байт (не char).

Для больших файлов требуется почти время.

Почему бы не sed

Проблема с решением sed, например sed '$ s/.$//' file, заключается в том, что он сначала считывает весь файл (длительное время с большими файлами), тогда вам нужен временный файл (того же размера, что и оригинал):

sed '$ s/.$//' file  > tempfile
rm file; mv tempfile file

И затем переместите файл temp, чтобы заменить файл.

Ответ 3

Здесь другой, использующий ex, который я считаю не таким загадочным, как решение sed:

 printf '%s\n' '$' 's/.$//' wq | ex somefile

$ переходит к последней строке, s удаляет последний символ, а wq - хорошо известный (для пользователей vi) write + quit.

Ответ 4

После целой группы игр с разными стратегиями (и избегая sed -i или perl), лучший способ, которым я нашел это, заключался в следующем:

sed '$! { P; D; }; s/.$//' somefile

Ответ 5

ОТДЕЛЬНЫЙ ОТВЕТ

Я создал script и разместил текст на своем рабочем столе. этот тестовый файл сохраняется как "old_file.txt"

sometext
moretext
lastline

Затем я написал небольшой script, чтобы взять старый файл и исключить символ last в последней строке

#!/bin/bash
no_of_new_line_characters=`wc  '/root/Desktop/old_file.txt'|cut -d ' ' -f2`
let "no_of_lines=no_of_new_line_characters+1"
sed -n 1,"$no_of_new_line_characters"p  '/root/Desktop/old_file.txt' > '/root/Desktop/my_new_file'
sed -n "$no_of_lines","$no_of_lines"p '/root/Desktop/old_file.txt'|sed 's/.$//g' >> '/root/Desktop/my_new_file'

открытие нового файла, который я создал, показал результат следующим образом:

sometext
moretext
lastlin

Приносим извинения за мой предыдущий ответ (не читал внимательно)

Ответ 6

Если цель состоит в том, чтобы удалить последний символ в последней строке, этот awk должен сделать:

awk '{a[NR]=$0} END {for (i=1;i<NR;i++) print a[i];sub(/.$/,"",a[NR]);print a[NR]}' file
sometext
moretext
lastlin

Сохраняет все данные в массиве, затем распечатывает и изменяет последнюю строку.

Ответ 7

Просто замечание: sed временно удалит файл. Поэтому, если вы завершаете файл, вы получите предупреждение "Нет такого файла или каталога", пока вы не переиздаете команду "хвост".

Ответ 8

sed 's/.$//' filename | tee newFilename

Это должно выполнить вашу работу.