быстрое удаление строки с индексом из файла

#shell #sed #awk

#оболочка #sed #awk

Вопрос:

У меня ОГРОМНЫЙ файл размером 10 ГБ. Я хочу удалить строку 188888 из этого файла.

Я использую sed следующим образом:

 sed -i '188888d' file
  

Проблема в том, что это действительно медленно. Я понимаю, что это из-за размера файла, но есть ли какой-нибудь способ сделать это быстрее.

Спасибо

Комментарии:

1. Все строки одинаковой длины или длина строки вычисляется по номеру строки? Потому что, если это не так, каждый байт перед строкой должен быть прочитан.

2. Строки имеют разную длину…

3. Тогда ответ на ваш вопрос, к сожалению, отрицательный.

4. Я вроде как не согласен, почему wc -l намного быстрее? Он в основном выполняет ту же операцию, верно?

5. Если я сделаю head и tail и соединю их вместе, это будет быстрее…

Ответ №1:

Попробуйте

 sed -i '188888{;d;q;}' file
  

Возможно, вам придется поэкспериментировать с тем, какие из приведенных выше точек с запятой вы сохраняете, {d;q} ... это 2-я вещь, которую нужно попробовать.

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

 sed '188888{;q;d;}' file > /path/to/alternate/mountpoint/newFile
  

где альтернативная точка монтирования находится на отдельном диске.

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

  yourLogFileProducingProgram | sed -i '188888d' > logFile
  

Но это предполагает, что вы знаете, что данные, которые вы хотите удалить, всегда находятся в строке ‘188888, возможно ли это?

Надеюсь, это поможет.

Комментарии:

1. См. Редактирование 30 секунд назад. Согласно другим комментариям, вы даже не можете написать пользовательскую программу на C, потому что случайные и переменные длины строк делают невозможным вычисление смещения (и в любом случае, большая часть времени уходит на перезапись файла). Sed занимает мало места в exe по сравнению с любым другим языком сценариев или java и этой парадигмой. Это одноразовая проблема, или вы говорите о повторяющейся проблеме. Если повторяется, то определенно стоит потратить время на поиск самого быстрого решения, в противном случае sed, вероятно, ваш лучший выбор. Удачи!

2. последнее редактирование выше. заключительный комментарий, вы можете захотеть, чтобы это происходило быстрее, но запись файла размером 10 миллионов занимает много времени. Можете ли вы пересмотреть свою стратегию в отношении файлов журналов? создавайте новую строку каждый час или 10 минут или?? в соответствии с вашим приложением. Удачи.

Ответ №2:

Строки файла определяются путем подсчета символа n, если размер строки является переменным, то вы не можете вычислить смещение к местоположению, заданному строке, но должны подсчитать количество новых строк.

Это всегда будет O (n), где n — количество байтов в файле.

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

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

Простой способ — создать индекс с

 line#:offset
  

И когда вы хотите найти строку, выполните двоичный поиск (Log n) в индексе для нужного номера строки и используйте смещение, чтобы найти строку в исходном файле.