Эффективное оперативное удаление заголовка для больших файлов с помощью sed?

Выезд lsyncd.

Lsyncd наблюдает локальный интерфейс контроля события деревьев каталогов (inotify). Это агрегировало и комбинирует события в течение нескольких секунд и затем порождает одну (или больше) процесс (процессы) для синхронизации изменений. По умолчанию это - rsync. Lsyncd является таким образом легким живым зеркальным решением, которое сравнительно легко установить не требующие новые файловые системы или blockdevices и не препятствует производительности локальной файловой системы.

Это не двухсторонне, но от Вашего вопроса я понял, что Вам не нужно это также. При необходимости в двухсторонней синхронизации Унисон является хорошим ответом, кроме нет никакой поддержки inotify. Кроме того, проверьте этот вопрос.

Третьей вещью для двухсторонней синхронизации является DRBD, блочный уровень система синхронизации в реальном времени, включенная в ядро магистрали. К сожалению, поскольку это почти синхронно, это требует быстрого соединения.

24
29.11.2011, 12:07
5 ответов

Попробовать ed вместо этого:

ed <<< $'1d\nwq' large_file

Если это “большое” означает приблизительно 10 миллионов строк или больше, лучше используйте tail. Не может для оперативного редактирования, но его производительность делает то отсутствие простительным:

tail -n +2 large_file > large_file.new

Редактирование для показа некоторой разницы во времени:

(awk код Jaypal, добавленным, чтобы иметь время выполнения на той же машине (ЦП 2.2 ГГц).)

bash-4.2$ seq 1000000 > bigfile.txt # further file creations skipped

bash-4.2$ time sed -i 1d bigfile.txt
time 0m4.318s

bash-4.2$ time ed -s <<< $'1d\nwq' bigfile.txt
time 0m0.533s

bash-4.2$ time perl -pi -e 'undef$_ if$.==1' bigfile.txt
time 0m0.626s

bash-4.2$ time { tail -n +2 bigfile.txt > bigfile.new && mv -f bigfile.new bigfile.txt; }
time 0m0.034s

bash-4.2$ time { awk 'NR>1 {print}' bigfile.txt > newfile.txt && mv -f newfile.txt bigfile.txt; }
time 0m0.328s
35
27.01.2020, 19:40
  • 1
    В случае tail, Я считал бы время, чтобы сделать и удалить первую строку и замену bigfile.txt с bigfile.new. –  rozcietrzewiacz 29.11.2011, 16:30
  • 2
    @rozcietrzewiacz оболочки, Ваша точка корректна.Спасибо. Обновленный. –  manatwork 29.11.2011, 16:57
  • 3
    Это действительно прохладно! Я сделал то же с awk и получил следующий результат - [jaypal:~/Temp] seq 1000000 > bigfile.txt [jaypal:~/Temp] time awk 'NR>1 {print}' bigfile.txt >newfile.txt real 0m0.649s user 0m0.601s sys 0m0.033s –  jaypal singh 29.11.2011, 22:29
  • 4
    @Jaypal, я добавил Ваш код к списку альтернатив. На моей машине это было еще быстрее. Странный, я ожидал awkпроизводительность для завершения к sed. (Отметьте мне: никогда не ожидайте – тест вместо этого.) –  manatwork 30.11.2011, 09:49
  • 5
    Это было лучшим решением в моем случае: tail -n +2 bigfile.txt > bigfile.new && mv -f bigfile.new bigfile.txt; Я использую единственный файл с блокировкой для отслеживания единственный список задач, используемый несколькими процессами. Я запустил с того, что использовал первоначальный плакат: sed -i 1d large_file . Это заставляло файл блокировать в течение 1-2 секунд. tail/mv комбинация завершается почти мгновенно.Спасибо! –  Chris Adams 11.04.2017, 15:50

Нет никакого способа эффективно удалить вещи из запуска файла. Удаление данных с начала требует перезаписи целого файла.

Усечение от конца файла может быть очень быстрым хотя (ОС только должна скорректировать информацию о размере файла, возможно разрешив теперь неиспользованные блоки). Это не обычно возможно, когда Вы пытаетесь удалить от главы файла.

Это могло теоретически быть "быстро", если бы Вы удалили целый блок/степень точно, но нет никаких системных вызовов этого, таким образом, необходимо было бы полагаться на определенную для файловой системы семантику (если такой существовать). (Или имеющий некоторую форму смещения в первом блоке/степени, который отметит реальный запуск файла, я предполагаю. Никогда не слышал об этом также.)

6
27.01.2020, 19:40
  • 1
    Если файл будет очень большим, то ввод-вывод наверху, вероятно, будет (возможно очень) больше, чем ЦП, наверху требуемый обработать конец строк. –  Mat 29.11.2011, 12:46
  • 2
    Вы правы. Однако могло быть различие в способе, которым инструменты получают доступ к содержанию файла. Лучшей не является технологическая линия, с методической точностью если не необходимая или по крайней мере не читающая линию за линией если не необходимый. –  manatwork 29.11.2011, 12:56
  • 3
    я удивлен различие, является настолько большим в Ваших результатах и может воспроизвести его с тем размером файла здесь. Преимущества, кажется, уменьшаются, когда размер файла увеличивается хотя (попробовал seq 10M, 15 для sed, 5 с для редактора). Хорошие советы так или иначе (+1). –  Mat 29.11.2011, 13:13
  • 4
    Начиная с версии 3.15, Linux теперь имеет API для сворачивания частей файла в некоторых основанных на степени файловых системах, но по крайней мере для ext4, который может только быть сделан на полных блоках (обычно 4k). –  Stéphane Chazelas 24.11.2014, 15:20
  • 5
    , Даже если редактирование требует перезаписи всего файла, иногда очень удобно иметь инструменты командной строки для эффективного редактирования. В моем случае это помогло, когда я должен был удалить первую строку файла, который был больше, чем моя общая системная RAM. –  Jason 01.06.2017, 08:10

Наиболее эффективный способ, не делайте этого! Если Вы делаете, в любом случае, Вам нужно дважды 'большое' пространство на диске, и Вы тратите впустую iOS.

Если Вы застреваете с большим файлом, который Вы хотите считать без 1-й строки, ожидать, пока Вы не должны читать ее для удаления 1-й строки. Если необходимо отправить файл от stdin до программы, используйте хвост, чтобы сделать это:

tail -n +2 | your_program

Когда необходимо считать файл, можно воспользоваться возможностью для удаления 1-й строки, но только если у Вас есть необходимое пространство на диске:

tail -n +2 | tee large_file2 | your_program

Если Вы не можете читать из stdin, используйте FIFO:

mkfifo large_file_wo_1st_line
tail -n +2 large_file > large_file_wo_1st_line&
your_program -i large_file_wo_1st_line

из еще лучше при использовании удара используйте в своих интересах замену процесса:

your_program -i <(tail -n +2 large_file)

Если Вам нужен поиск в файле, я не вижу лучшего решения, чем не застревание с файлом во-первых. Если этот файл был сгенерирован stdout:

large_file_generator | tail -n +2 > large_file

Еще, всегда существует решение для замены FIFO или процесса:

mkfifo large_file_with_1st_file
large_file_generator -o large_file_with_1st_file&
tail -n +2 large_file_with_1st_file > large_file_wo_1st_file

large_file_generator -o >(tail -n 2+ > large_file_wo_1st_file)
3
27.01.2020, 19:40

Это просто теоретизирует, но...

Пользовательская файловая система (реализованное использование FUSE или подобный механизм) могла выставить каталог, содержание которого является точно тем же как уже существующим каталогом где-то в другом месте, но с файлами, усеченными, как Вы желаете. Файловая система перевела бы все файловые смещения. Затем Вы не должны были бы делать трудоемкой перезаписи файла.

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

0
27.01.2020, 19:40

Вы можете использовать Vim в режиме Ex:

ex -sc '1d|x' large_file
  1. 1 выберите первую строку

  2. d удалить

  3. x сохранить и закрыть

1
27.01.2020, 19:40

Теги

Похожие вопросы