11 ответов:
Использование
GNU sed:sed -i '$ d' foo.txtОпция
-iне существует в версияхGNU sedстарше 3.95, поэтому вы должны использовать ее в качестве фильтра с временным файлом:Конечно, в этом случае вы также можете использоватьcp foo.txt foo.txt.tmp sed '$ d' foo.txt.tmp > foo.txt rm -f foo.txt.tmphead -n -1вместоsed.
Это, безусловно, самое быстрое и простое решение, особенно для больших файлов:
head -n -1 foo.txt > temp.txt ; mv temp.txt foo.txtЕсли вы хотите удалить верхнюю строку, используйте следующее:
tail -n +2 foo.txt, Что означает выходные линии, начинающиеся со строки 2.
Не используйте
sedдля удаления строк из верхней или нижней части файла-это очень медленно, если файл большой.
У меня были проблемы со всеми ответами здесь, потому что я работал с огромным файлом (~300 ГБ), и ни одно из решений не масштабировалось. Вот мое решение:
dd if=/dev/null of=<filename> bs=1 seek=$(echo $(stat --format=%s <filename> ) - $( tail -n1 <filename> | wc -c) | bc )В словах: узнайте длину файла, который вы хотите закончить (длина файла минус длина его последней строки, используя
bc), и установите эту позицию, чтобы быть концом файла (путемdding один байт/dev/nullна него).Это быстро, потому что
tailначинает чтение с конца, иddперезапишет файл на месте вместо копирования (и разбора) каждой строки файла, что и делают другие решения.Примечание: это удаляет строку из файла на месте! Сделайте резервную копию или протестируйте фиктивный файл, прежде чем опробовать его на своем собственном файле!
Чтобы удалить последнюю строку из файла , не читая весь файл и ничего не переписывая , можно использовать
tail -n 1 "$file" | wc -c | xargs -I {} truncate "$file" -s -{}Чтобы удалить последнюю строку и также распечатать ее на stdout ("pop" it), вы можете объединить эту команду с
tee:Эти команды могут эффективно обрабатывать очень большой файл. Это похоже на ответ Йоси и вдохновлено им, но позволяет избежать использования нескольких дополнительных функций.tail -n 1 "$file" | tee >(wc -c | xargs -I {} truncate "$file" -s -{})Если вы собираетесь использовать их повторно и хотите обработки ошибок и некоторые другие функции, вы можете использовать команду
poptailздесь: https://github.com/donm/evenmoreutils
Пользователи Mac
Если вы хотите удалить только последнюю строку вывода без изменения самого файла, сделайте
sed -e '$ d' foo.txtЕсли вы хотите удалить последнюю строку самого входного файла, сделайте
sed -i '' -e '$ d' foo.txt
Для Пользователей Mac:
На Mac, head-n -1 не будет работать. И я пытался найти простое решение [ не беспокоясь о времени обработки], чтобы решить эту проблему только с помощью команд "head" и/или "tail".
Я попробовал следующую последовательность команд и был счастлив, что смог решить ее, просто используя команду "tail" [с опциями, доступными на Mac ]. Итак, если вы находитесь на Mac и хотите использовать только "хвост" для решения этой проблемы, вы можете использовать следующую команду:
Кот файл.txt / tail-r / tail-n +2 / tail-r
Пояснение:
1> tail-r: просто меняет порядок строк на своем входе
2> tail-n +2: выводит все строки, начиная со второй строки на входе
awk 'NR>1{print buf}{buf = $0}'По существу, этот код говорит следующее:
Для каждой строки после первой выведите буферизованную строку
Для каждой строки сбросьте буфер
Буфер запаздывает на одну строку, поэтому вы в конечном итоге печатаете строки от 1 до n-1
Оба эти решения представлены здесь в других формах. Я нашел их немного более практичными, ясными и полезными:
Используя dd:
BADLINESCOUNT=1 ORIGINALFILE=/tmp/whatever dd if=${ORIGINALFILE} of=${ORIGINALFILE}.tmp status=none bs=1 count=$(printf "$(stat --format=%s ${ORIGINALFILE}) - $(tail -n${BADLINESCOUNT} ${ORIGINALFILE} | wc -c)\n" | bc ) /bin/mv -f ${ORIGINALFILE}.tmp ${ORIGINALFILE}Использование усечения:
BADLINESCOUNT=1 ORIGINALFILE=/tmp/whatever truncate -s $(printf "$(stat --format=%s ${ORIGINALFILE}) - $(tail -n${BADLINESCOUNT} ${ORIGINALFILE} | wc -c)\n" | bc ) ${ORIGINALFILE}
Comments