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

Как удалить первую строку текстового файла с помощью bash/sed script?

Мне нужно многократно удалить первую строку из огромного текстового файла с помощью bash script.

Сейчас я использую sed -i -e "1d" $FILE - но для удаления требуется около минуты.

Есть ли более эффективный способ сделать это?

4b9b3361

Ответ 1

Попробуй хвост:

tail -n +2 "$FILE"

-n x: просто напечатать последние x строк. tail -n 5 выдаст вам последние 5 строк ввода. Знак + инвертирует аргумент и заставляет tail печатать что угодно, кроме первых строк x-1. tail -n +1 будет печатать весь файл, tail -n +2 все, кроме первой строки и т.д.

tail GNU намного быстрее, чем sed. tail также доступен в BSD, и флаг -n +2 одинаков для обоих инструментов. Проверьте справочные страницы FreeBSD или OS X для получения дополнительной информации.

Версия BSD может быть намного медленнее, чем sed. Интересно, как им это удалось; tail должен просто читать файл построчно, в то время как sed выполняет довольно сложные операции, включая интерпретацию скрипта, применение регулярных выражений и тому подобное.

Примечание: вы можете испытать желание использовать

# THIS WILL GIVE YOU AN EMPTY FILE!
tail -n +2 "$FILE" > "$FILE"

но это даст вам пустой файл. Причина в том, что перенаправление (>) происходит до того, как оболочка вызовет tail:

  1. Обрезает файл оболочки $FILE
  2. Shell создает новый процесс для tail
  3. Оболочка перенаправляет стандартный вывод tail процесса в $FILE
  4. tail читает из пустого $FILE

Если вы хотите удалить первую строку внутри файла, вы должны использовать:

tail -n +2 "$FILE" > "$FILE.tmp" && mv "$FILE.tmp" "$FILE"

&& гарантирует, что файл не будет перезаписан при возникновении проблемы.

Ответ 2

Вы можете использовать -i для обновления файла без использования оператора ' > '. Следующая команда удалит первую строку из файла и сохранит ее в файле.

sed -i '1d' filename

Ответ 3

Для тех, кто находится на SunOS, который не является GNU, следующий код поможет:

sed '1d' test.dat > tmp.dat 

Ответ 4

Нет, это так же эффективно, как и вы. Вы могли бы написать программу на C, которая могла бы выполнить задание немного быстрее (меньше времени запуска и аргументов обработки), но она, вероятно, будет стремиться к той же скорости, что и sed, поскольку файлы становятся большими (и я предполагаю, что они большие, если он занимает минуту).

Но ваш вопрос страдает от той же проблемы, что и многие другие, поскольку он предполагает решение. Если вы хотите подробно рассказать нам , что, а не как, мы можем предложить лучший вариант.

Например, если это файл A, который обрабатывает какая-либо другая программа B, одно решение состоит в том, чтобы не отделять первую строку, а изменять программу B, чтобы обрабатывать ее по-разному.

Скажем, все ваши приложения присоединяются к этому файлу A, а программа B в настоящее время считывает и обрабатывает первую строку перед удалением.

Вы могли бы повторно спроектировать программу B, чтобы она не пыталась удалить первую строку, но поддерживала постоянное (возможно, основанное на файле) смещение в файле A, чтобы в следующий раз он мог искать это смещать, обрабатывать линию там и обновлять смещение.

Затем, в спокойное время (полночь?), он мог бы выполнить специальную обработку файла A для удаления всех обрабатываемых в настоящее время строк и установить смещение обратно на 0.

Конечно, программа будет быстрее открывать и искать файл, а не открывать и переписывать. Это обсуждение предполагает, что вы контролируете программу B, конечно. Я не знаю, может ли это быть, но могут быть другие возможные решения, если вы предоставите дополнительную информацию.

Ответ 5

Вы можете редактировать файлы на месте: просто используйте perl -i флаг, например:

perl -ni -e 'print unless $. == 1' filename.txt

Это приводит к тому, что первая строка исчезает, как вы просите. Perl необходимо будет прочитать и скопировать весь файл, но он упорядочивает вывод, который будет сохранен под именем исходного файла.

Ответ 6

Как сказал Пакс, вы, скорее всего, не добьетесь этого быстрее. Причина в том, что почти нет файловых систем, которые поддерживают усечение с самого начала файла, так что это будет операция O (n), где n - размер файла. То, что вы можете сделать намного быстрее, хотя и перезаписывает первую строку с таким же количеством байтов (возможно, с пробелами или комментарием), которые могут работать для вас в зависимости от того, что вы пытаетесь сделать (что это, кстати?).

Ответ 7

Утилита sponge избавляет от необходимости манипулирования временным файлом:

tail -n +2 "$FILE" | sponge "$FILE"

Ответ 8

Если вы хотите изменить файл в месте, вы всегда можете использовать оригинальный ed вместо его с treaming преемником sed:

ed "$FILE" <<<$'1d\nwq\n'

Команда ed была оригинальным текстовым редактором UNIX, еще до появления полноэкранных терминалов, а тем более графических рабочих станций. ex редактор, наиболее известный как то, что вы используете при вводе в командной строке двоеточия в vi, является расширенной версией ed, поэтому многие из тех же команд работают. Хотя ed предназначен для использования в интерактивном режиме, он также может использоваться в пакетном режиме, посылая ему строку команд, что и делает это решение.

Последовательность <<<$'1d\nwq\n' использует поддержку Bash для строк here (<<<) и кавычек POSIX ($'... ') для подачи ввода в команду ed состоящую из двух строк: 1d, что d eletes линия 1, а затем wq, что ж обряды файл обратно на диск, а затем д ПИФ сеанса редактирования.

Ответ 9

Может использовать vim для этого:

vim -u NONE +'1d' +'wq!' /tmp/test.txt

Это должно быть быстрее, так как vim не будет читать весь файл при обработке.

Ответ 10

Как насчет использования csplit?

man csplit
csplit -k file 1 '{1}'

Ответ 11

должен показывать строки, кроме первой строки:

cat textfile.txt | tail -n +2

Ответ 12

Вы можете легко сделать это с:

cat filename | sed 1d > filename_without_first_line

в командной строке; или чтобы окончательно удалить первую строку файла, используйте режим sed на -i флагом -i:

sed -i 1d <filename>

Ответ 13

Поскольку это звучит так, как будто я не могу ускорить удаление, я думаю, что хорошим подходом может быть обработка файла такими партиями, как это:

While file1 not empty
  file2 = head -n1000 file1
  process file2
  sed -i -e "1000d" file1
end

Недостаток этого заключается в том, что если программа будет убита посередине (или если там какой-то плохой sql там, из-за чего часть процесса будет умирать или заперта), будут пропущены строки, или обрабатывается дважды.

(файл1 содержит строки кода sql)

Ответ 14

Если то, что вы хотите сделать, это восстановить после сбоя, вы можете просто создать файл с тем, что вы сделали до сих пор.

if [[ -f $tmpf ]] ; then
    rm -f $tmpf
fi
cat $srcf |
    while read line ; do
        # process line
        echo "$line" >> $tmpf
    done

Ответ 15

Использует хвост на линиях N-1 и направляет его в файл, а затем удаляет старый файл и переименовывает новый файл в старое имя, выполнив задание?

Если бы я делал это программно, я бы читал файл и помнил смещение файла после прочтения каждой строки, поэтому я мог бы вернуться к этой позиции, чтобы прочитать файл с меньшей линией.