У меня есть файл foo.txt, содержащий следующие строки:
a
b
c
Я хочу простую команду, которая приводит к содержанию foo.txtбытия:
a
b
У меня есть файл foo.txt, содержащий следующие строки:
a
b
c
Я хочу простую команду, которая приводит к содержанию foo.txtбытия:
a
b
Ответы:
Использование 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.tmp
Конечно, в этом случае вы также можете использовать head -n -1вместо sed.
MacOS:
В Mac OS X (по состоянию на 10.7.4) эквивалент sed -iкоманды выше
sed -i '' -e '$ d' foo.txt
$ dрегулярным выражением. Это команда sed. dэто команда для удаления строки, в то время как $означает «последняя строка в файле». При указании местоположения (называемого «диапазон» в sed lingo) перед командой эта команда применяется только к указанному местоположению. Таким образом, эта команда явно говорит: «в диапазоне последней строки в файле, удалите его». Довольно гладко и прямо к делу, если вы спросите меня.
На сегодняшний день это самое быстрое и простое решение, особенно для больших файлов:
head -n -1 foo.txt > temp.txt ; mv temp.txt foo.txt
если вы хотите удалить верхнюю строку, используйте это:
tail -n +2 foo.txt
что означает выходные строки, начинающиеся со строки 2.
Не используйте sedдля удаления строк сверху или снизу файла - это очень очень медленно, если файл большой.
head -n -1 foo.txtдостаточно
brew install coreutils(основные утилиты GNU) и использовать gheadвместо head.
FILE=$1; TAIL=$2; head -n -${TAIL} ${FILE} > temp ; mv temp ${FILE}Запустите его для удаления 4 строк, например, из myfile, как: ./TAILfixer myfile 4конечно, сначала сделайте его исполняемым с помощьюchmod +x TAILfixer
sed, эта команда тоже чертовски медленная
У меня были проблемы со всеми ответами здесь, потому что я работал с огромным файлом (~ 300 Гб), и ни одно из решений не масштабировалось. Вот мое решение:
dd if=/dev/null of=<filename> bs=1 seek=$(echo $(stat --format=%s <filename> ) - $( tail -n1 <filename> | wc -c) | bc )
Другими словами: определите длину файла, который вы хотите получить (длина файла минус длина его последней строки, используя bc), и установите эту позицию как конец файла (используя ddодин байт /dev/nullна Это).
Это быстро, потому что tailначинает чтение с конца и ddперезаписывает файл на месте, а не копирует (и анализирует) каждую строку файла, что и делают другие решения.
ПРИМЕЧАНИЕ: это удаляет строку из файла на месте! Сделайте резервную копию или протестируйте фиктивный файл перед тем, как опробовать его на своем собственном файле!
Чтобы удалить последнюю строку из файла, не читая весь файл и не переписывая что-либо , вы можете использовать
tail -n 1 "$file" | wc -c | xargs -I {} truncate "$file" -s -{}
Чтобы удалить последнюю строку, а также вывести ее на стандартный вывод («вывести»), вы можете объединить эту команду с tee:
tail -n 1 "$file" | tee >(wc -c | xargs -I {} truncate "$file" -s -{})
Эти команды могут эффективно обрабатывать очень большой файл. Это похоже на ответ Йосси и вдохновлено им, но избегает использования нескольких дополнительных функций.
Если вы собираетесь использовать их несколько раз и хотите обрабатывать ошибки и некоторые другие функции, вы можете использовать poptailкоманду здесь:
https://github.com/donm/evenmoreutils
truncateне доступно в OS X по умолчанию. Но это легко установить с помощью Brew: brew install truncate.
Пользователи Mac
если вы хотите, чтобы последняя строка удаляла вывод без изменения самого файла, сделайте
sed -e '$ d' foo.txt
если вы хотите удалить последнюю строку самого входного файла, сделайте
sed -i '' -e '$ d' foo.txt
-i ''указывает sed изменять файл на месте, сохраняя резервную копию в файле с расширением, предоставленным в качестве параметра. Поскольку параметр является пустой строкой, файл резервной копии не создается. -eговорит sed выполнить команду. Команда $ dозначает: найти последнюю строку ( $) и удалить ее ( d).
На Mac голова -n -1 не будет работать. И я пытался найти простое решение [не беспокоясь о времени обработки], чтобы решить эту проблему только с помощью команд «head» и / или «tail».
Я попробовал следующую последовательность команд и был счастлив, что смог решить ее, используя команду «tail» [с опциями, доступными на Mac]. Итак, если вы находитесь на Mac и хотите использовать только «хвост» для решения этой проблемы, вы можете использовать эту команду:
кошка file.txt | хвост -r | tail -n +2 | хвост -r
1> tail -r: просто меняет порядок строк на входе
2> tail -n +2: печатает все строки, начиная со второй строки в своем входе
ghead -n -1
awk 'NR>1{print buf}{buf = $0}'
По сути, этот код говорит следующее:
Для каждой строки после первой выведите буферизованную строку
для каждой строки сбросьте буфер
Буфер отстает на одну строку, следовательно, вы заканчиваете печать строк от 1 до n-1
awk "NR != `wc -l < text.file`" text.file |> text.file
Этот фрагмент делает свое дело.
Оба эти решения находятся здесь в других формах. Я нашел это немного более практичным, понятным и полезным:
Используя дд:
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}
sed '$d' ~/path/to/your/file/name
sed -i '' -e '$ d' ~/path/to/your/file/name
Вот как вы можете сделать это вручную (я лично часто использую этот метод, когда мне нужно быстро удалить последнюю строку в файле):
vim + [FILE]
Который + знак означает, что когда файл открывается в текстовом редакторе vim, курсор будет помещен в последнюю строку файла.
Теперь просто dдважды нажмите на клавиатуре. Это будет делать именно то, что вы хотите - удалить последнюю строку. После этого нажмите :, xа затем нажмите Enter. Это сохранит изменения и вернет вас в оболочку. Теперь последняя строка была успешно удалена.
sed -iкоманды вышеsed -i '' -e '$ d' foo.txt. Кроме того, вhead -n -1настоящее время не будет работать на Mac.