Как удалить первую строку текстового файла с помощью скрипта bash/sed?
Мне нужно повторно удалить первую строку из огромного текстового файла с помощью скрипта bash.
сейчас я использую sed -i -e "1d" $FILE - но это занимает около минуты, чтобы сделать удаление.
есть ли более эффективный способ сделать это?
14 ответов:
попробовать GNU tail:
tail -n +2 "$FILE"
-n x: просто распечатайте последнийxстроки.tail -n 5даст вам последние 5 строк ввода. Элемент+знак рода инвертирует аргумент и сделатьtailпечатать все, кроме первогоx-1строки.tail -n +1напечатал бы весь файл,tail -n +2все, кроме первой строки, и т. д.GNU
tailгораздо быстрее, чемsed.tailтакже доступно на BSD и-n +2флаг согласовано в обоих инструментах. Проверьте FreeBSD или OS X man-страницы для более.версия BSD может быть намного медленнее, чем
sed, хотя. Интересно, как им это удалось;tailнадо просто читать файл построчно, покаsedвыполняет довольно сложные операции, связанные с интерпретацией скрипта, применением регулярных выражений и тому подобное.Примечание: у вас может возникнуть искушение использовать
# THIS WILL GIVE YOU AN EMPTY FILE! tail -n +2 "$FILE" > "$FILE"но это даст вам пустой файл. Причина в том, что перенаправление (
>) происходит передtailвызывается оболочкой:
- оболочка усекает файл
$FILE- Shell создает новый процесс для
tail- оболочка перенаправляет stdout из
вы можете использовать-i для обновления файла без использования оператора'>'. Следующая команда удалит первую строку из файла и сохранит ее в файл.
sed -i '1d' filename
для тех, кто находится на SunOS, который не является GNU, следующий код поможет:
sed '1d' test.dat > tmp.dat
нет, это примерно так же эффективно, как вы собираетесь получить. Вы можете написать программу на C, которая может выполнять эту работу немного быстрее (меньше времени запуска и обработки аргументов), но она, вероятно, будет стремиться к той же скорости, что и sed, когда файлы становятся большими (и я предполагаю, что они большие, если это займет минуту).
но ваш вопрос страдает от той же проблемы, что и многие другие, в том, что он предполагает решение. Если бы вы рассказали нам подробно что ты пытаешься делай скорее тогда как, мы можем предложить лучший вариант.
например, если это файл A, который обрабатывает какая-то другая программа B, одним из решений было бы не удалять первую строку, а изменить программу B, чтобы обработать ее по-другому.
предположим, что все ваши программы добавляют к этому файлу A и программа B в настоящее время читает и обрабатывает первую строку перед ее удалением.
вы можете перепроектировать программу B, чтобы она не пыталась удалить первая строка, но поддерживает постоянное (вероятно, файловое) смещение в файл A, чтобы при следующем запуске он мог искать это смещение, обрабатывать строку там и обновлять смещение.
затем, в спокойное время (полночь?), он может выполнить специальную обработку файла A, чтобы удалить все строки, которые в настоящее время обрабатываются, и установить смещение обратно в 0.
Это, безусловно, будет быстрее для программы, чтобы открыть и искать файл, а не открывать и переписывать. Это обсуждение предполагает, что вы иметь контроль над программой, разумеется. Я не знаю, так ли это, но могут быть и другие возможные решения, если вы предоставите дополнительную информацию.
вы можете редактировать файлы на месте: просто используйте perl
-iфлаг, как это:perl -ni -e 'print unless $. == 1' filename.txtэто делает первую строку исчезают, как вы спрашиваете. Perl нужно будет прочитать и скопировать весь файл, но он организует для вывода, который будет сохранен под именем исходного файла.
Как сказал Пакс, вы, вероятно, не получите быстрее, чем это. Причина в том, что практически нет файловых систем, которые поддерживают усечение с начала файла, так что это будет O (
nоперации), гдеnразмер файла. Что вы можете сделать много быстрее, хотя перезаписать первую строку с тем же количеством байтов (возможно, с пробелами или комментарием), которые могут работать для вас в зависимости от того, что именно вы пытаетесь сделать (что такое это кстати?).
The
spongeполезное позволяет избежать необходимости жонглирования временным файлом:tail -n +2 "$FILE" | sponge "$FILE"
можно использовать Vim для этого:
vim -u NONE +'1d' +'wq!' /tmp/test.txtЭто должно быть быстрее, так как vim не будет читать весь файл, когда процесс.
Если вы хотите изменить файл на месте, вы всегда можете использовать оригинал
edвместо streaming правопреемникомsed:ed "$FILE" <<<$'1d\nwq\n'
поскольку это звучит так, как будто я не могу ускорить удаление, я думаю, что хорошим подходом может быть обработка файла в таких пакетах:
While file1 not empty file2 = head -n1000 file1 process file2 sed -i -e "1000d" file1 endнедостатком этого является то, что если программа будет убита в середине (или если там есть какой - то плохой sql-в результате чего часть "процесса" умирает или блокируется), будут строки, которые либо пропущены, либо обработаны дважды.
(файл1 содержит строки кода sql)
Если то, что вы хотите сделать, это восстановить после сбоя, вы могли бы просто создать файл, который имеет то, что вы сделали до сих пор.
if [[ -f $tmpf ]] ; then rm -f $tmpf fi cat $srcf | while read line ; do # process line echo "$line" >> $tmpf done
будет ли использование хвоста на N-1 строках и направление его в файл, а затем удаление старого файла и переименование нового файла в старое имя выполнять эту работу?
Если бы я делал это программно, я бы прочитал файл и запомнил смещение файла после чтения каждой строки, чтобы я мог вернуться в эту позицию, чтобы прочитать файл с одной строкой меньше.
Comments