У меня есть файл 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.