Как удалить первую строку текстового файла с помощью bash/sed?
Я должен многократно удалять первую строку из огромного текстового файла с помощью bash-скрипта.
В данный момент я использую команду sed -i -e "1d" $FILE
, но на выполнение операции уходит около минуты.
Есть ли более эффективный способ решить эту проблему?
5 ответ(ов)
Для тех, кто работает на SunOS, который не является GNU, следующий код поможет:
sed '1d' test.dat > tmp.dat
Эта команда удалит первую строку из файла test.dat
и сохранит результат в файле tmp.dat
.
Вы можете легко сделать это с помощью следующей команды в терминале:
cat имя_файла | sed 1d > имя_файла_без_первой_строки
Если вы хотите навсегда удалить первую строку из файла, используйте режим редактирования на месте с флагом -i
:
sed -i 1d имя_файла
Нет, это достаточно эффективно. Вы можете написать программу на C, которая справится с задачей немного быстрее (меньше времени на запуск и обработку аргументов), но с увеличением размера файлов она, вероятно, будет стремиться к такой же скорости, как и sed
(и я предполагаю, что файлы большие, если на это уходит минуту).
Однако ваш вопрос сталкивается с той же проблемой, что и многие другие, а именно, что он предполагает решение. Если бы вы рассказали нам подробнее, что именно вы пытаетесь сделать, а не как, возможно, мы смогли бы предложить более подходящее решение.
Например, если у вас есть файл A, который обрабатывает другая программа B, то одним из решений было бы не удалять первую строку, а изменить программу B, чтобы она обрабатывала ее по-другому.
Допустим, все ваши программы добавляют данные в этот файл A, и программа B в настоящее время считывает и обрабатывает первую строку перед ее удалением.
Вы могли бы переработать программу B так, чтобы она не пыталась удалить первую строку, а вместо этого сохраняла постоянный (вероятно, основанный на файле) смещенный указатель в файле A, чтобы в следующий раз, когда она запустится, могла перейти к этому смещению, обработать строку и обновить указатель.
Затем, в спокойное время (полночь?), она могла бы выполнить специальную обработку файла A, чтобы удалить все строки, которые уже были обработаны, и сбросить указатель обратно на 0.
Для программы определенно будет быстрее открывать и перематывать файл, чем открывать и переписывать его. Это обсуждение предполагает, что у вас есть контроль над программой B, конечно. Я не знаю, так это или нет, но могут быть и другие возможные решения, если вы предоставите дополнительную информацию.
Если вы хотите изменить файл непосредственно, вы всегда можете использовать оригинальный редактор ed
, вместо его потокового преемника sed
:
ed "$FILE" <<<$'1d\nwq\n'
Команда ed
была оригинальным текстовым редактором UNIX до того, как появились полноэкранные терминалы, не говоря уже о графических рабочих станциях. Редактор ex
, наиболее известный как то, что вы используете, вводя команды с двоеточием в vi
, является расширенной версией ed
, так что многие команды будут работать и там. Хотя ed
предназначен для интерактивного использования, его также можно использовать в пакетном режиме, отправляя ему строку команд, что и делает данное решение.
Последовательность <<<$'1d\nwq\n'
использует поддержку современных оболочек для here-строк (<<<
) и ANSI кавычек ($'...'
), чтобы подать на вход команде ed
две строки: 1d
, которая удаляет первую строку, и затем wq
, которая сохраняет файл на диск и выходит из сессии редактирования.
Как уже упоминал Pax, вы вряд ли сможете добиться более высокой скорости, чем это. Причина в том, что почти нет файловых систем, которые поддерживают обрезку файла с начала, поэтому это будет операция O(n
), где n
– размер файла. Однако вы можете сделать значительно быстрее – перезаписать первую строку таким же количеством байт (например, пробелами или комментарием), что может сработать для вас в зависимости от того, что именно вы пытаетесь сделать (что это, кстати?).
Как запросить ввод Yes/No/Cancel в скрипте оболочки Linux?
Как работает "cat << EOF" в bash?
Как получить пароль из оболочки без вывода в терминал?
Как узнать имя скрипта в Bash?
Найти и заменить текст в файле через командную строку Bash