C Удалите первую строку из текстового файла без перезаписи файла

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

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

Итак, как мне удалить их?


6

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

Улучшите этот ответ
ответил 17 апреля ’10 в 12:45
добавить комментарий |

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


2

К сожалению, это невозможно сделать без перезаписи файла на месте или в виде отдельного файла.

Одна вещь, которую вы можете хотите посмотреть, — это сохранить указатель в другом файле, указав позицию первой необработанной строки.

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

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

Улучшите этот ответ
17 апр. ’10 в 12:46
добавить комментарий |

К сожалению, это невозможно без перезаписи файла на месте или в виде отдельного файла.

Одна вещь, на которую вы , возможно, захотите обратить внимание, — это сохранить указатель в другом файле, указав позицию первой необработанной строки.

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

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


0

Я не уверен, но я думаю так: New Line — это символ, поэтому вы должны удалить символы для этой строки + New Line char Кстати, «перемещение» всех символов назад (для перезаписи старой строки) похоже на копирование каждый символ в другой позиции и удаление их из их старой позиции

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

Улучшить этот ответ
ответил 17 апр. 45
добавить комментарий |

Я не уверен, но я думаю так: New Line — это символ, поэтому вы должны удалить символы для этого line + New Line char Кстати, «перемещение» всех символов назад (чтобы перезаписать старую строку) похоже на копирование каждого символа в другую позицию и удаление их из их старой позиции

Так что нет , Я не думаю, что вы можете просто удалить строку, вам следует переписать весь файл.


0

Вы не можете, файлы работают не так.

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

Улучшите этот ответ
ответил 17 апр. ’10 в 12:46
добавить комментарий |

Вы не можете, файлы работают не так.

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


0

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

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

Улучшите этот ответ
ответил апр. 17 ’10, 12:48
добавить комментарий |

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

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



Удалить первую строку файла

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

Я пробовал это, но он стирает все содержимое файла.

  $ sed 1d file.txt> file.txt  

Причина, по которой file.txt пуст после этой команды, — это порядок, в котором оболочка выполняет действия. Первое, что происходит с этой строкой, — это перенаправление. Файл «file.txt» открывается и обрезается до 0 байт. После этого запускается команда sed, но на данный момент файл уже пуст.

Есть несколько вариантов, большинство из которых связаны с записью во временный файл.

  sed '1d' file.txt> tmpfile;  mv tmpfile file.txt # POSIXsed -i '1d' file.txt # Только GNU sed, создает временный файл perl -ip -e '$ _ = undef if $.  == 1 'file.txt # также создает временный файл  

171

Альтернативный, очень легкий вариант — просто «хвостить» все, кроме первой строки (это может быть простым способом удалить заголовки файлов в целом):

  # -n +2: начать со строки 2 файла .tail -n +2 file.txt> file.stdout  

Следуя @Evan Teitelman, вы можете :

  tail -n +2 file.txt |  sponge file.txt  

Чтобы избежать временного файла. Другой вариант:

  echo "$ (tail -n +2 file.txt)"> file.txt  

И так далее. Тестирование последнего:

  [user @ work ~] $ cat file.txtline 1line 2line 3line 4line 5 [user @ work ~] $ echo "$ (tail -n +2  file.txt) "> file.txt [user @ work ~] $ cat файл. txtline 2line 3line 4line 5 [user @ work ~] $  

К сожалению, мы потеряли новую строку (на комментарий @ 1_CR ниже), попробуйте вместо этого:

   printf "% s  n  n" "$ (tail -n +2 file.txt)"> file.txt [user @ work ~] $ cat file.txtline 1line 2line 3line 4line 5 [user @  работа ~] $ printf '% s  n  n' "$ (tail -n +2 file.txt)"> file.txt [user @ work ~] $ cat file.txtline 2line 3line 4line 5 [user @ work ~  ] $  

Возвращаясь к sed, попробуйте:

  printf '% s  n  n' "$ (sed '  1d 'file.txt) "> file.txt  

или, возможно,

  echo -e" $ (sed' 1d '  file.txt)  n "> file.txt  

Чтобы избежать побочных эффектов.

Улучшите этот ответ
отредактировано 16 октября 2013 г. в 13:38

Ответ

16 октября 2013 г., 11:32
  • Я только что попробовал это в своей системе Fedora, и результат выше. Вы правы — спасибо, что указали на это. — AsymLabs, 16 окт., 13:02
  • У меня сработал трюк с tail (на файл 130 МБ он занял менее 3 секунд). Благодаря! — elo80ka 18 авг., 2014, 17:51
  • echo "$ (tail -n +2 file.txt)"> file.txt — идеальный ответ. — Алекс Радж Калиамурти, 22 ноя. 2016, 12:26
  • Спасибо! echo «$ (tail -n +2 file.txt)»> file.txt у меня работает как шарм! — Арсений 01 фев. В 14:01
  • 1
    Ответ echo -e имеет побочный эффект замены литералов » n» в файле фактическими новыми строками — Мохаммад Джафар Машхади, 7 февраля 2020 г., 22:20
| показать 1 дополнительный комментарий

Альтернативный, очень легкий вариант — просто «хвостить» за всем, кроме первого строка (обычно это простой способ удалить заголовки файлов):

  # -n +2: начать со строки 2 файла file.tail -n +2.  txt> file.stdout  

Следуя @Evan Teitelman, вы можете:

  tail -n +2 file.txt |  sponge file.txt  

Чтобы избежать временного файла. Другой вариант:

  echo "$ (tail -n +2 file.txt)"> file.txt  

И так далее. Тестирование последнего:

  [user @ work ~] $ cat file.txtline 1line 2line 3line 4line 5 [user @ work ~] $ echo "$ (tail -n +2  file.txt) "> файл. txt [user @ work ~] $ cat file.txtline 2line 3line 4line 5 [user @ work ~] $  

К сожалению, мы потеряли новую строку (на комментарий @ 1_CR ниже), попробуйте вместо этого:

  printf "% s  n  n" "$ (tail -n +2 file.txt)"> file.txt [user @ work ~] $ cat  file.txtline 1line 2line 3line 4line 5 [user @ work ~] $ printf '% s  n  n' "$ (tail -n +2 file.txt)"> file.txt [user @ work ~] $ cat файл  .txtline 2line 3line 4line 5 [user @ work ~] $  

Возвращаясь к sed, попробуйте:

  printf '%  s  n  n '"$ (sed' 1d 'file.txt)"> file.txt  

или, возможно,

  echo -e "$ (sed '1d' file.txt)  n"> file.txt  

Чтобы избежать побочных эффектов.


21

Эта тема интересна, поэтому я тестирую тест тремя способами:

  1. sed '1d' d.txt> tmp.txt
  2. tail -n +2 d.txt> tmp.txt
  3. sed -i '1d' d.txt ode>

Обратите внимание, что целевой d.txt — это файл размером 5,4 ГБ

Получите результат:


  run 1: sed '1d' d.txt> r1.txt14srun 2: tail -n +2 d.txt> r2.txt20srun 3: sed -i '  1d 'd.txt88s  

Заключение: кажется, что это самый быстрый способ:

sed ‘1d’ file.txt> tmpfile; mv tmpfile file.txt

Улучшите этот ответ
отредактировано 10 июня 2015 г., 04:29
TPS
2 35955 золотых знаков2424 серебряных знака4444 бронзовых знака
ответил 10 июня ’15 в 4:04
  • Ваш метод sed '1d' d.txt не включал (по крайней мере, так кажется, читая ваши тесты) mv команда. В моих тестах на FreeBSD с файлом размером 20 МБ команда sed -i была самой быстрой. — Сопалахо де Арьерес 11 фев. ’18 в 23:04
добавить комментарий |

Эта тема интересна, поэтому я тестирую тест тремя способами:

  1. sed '1d' d.txt> tmp.txt
  2. tail -n +2 d.txt> tmp.txt
  3. sed -i '1d' d.txt

Обратите внимание, что target d. txt — это файл размером 5,4 ГБ

Получите результат:


  выполните 1: sed '1d' d.  txt> r1.txt14srun 2: tail -n +2 d.txt> r2.txt20srun 3: sed -i '1d' d. txt88s  

Заключение: кажется, это самый быстрый способ:

sed ' 1d 'file.txt> tmpfile; mv tmpfile file.txt


18

Также обратите внимание на sponge из moreutils . sponge впитывает данные из стандартного ввода до тех пор, пока конец записи стандартного ввода не закроется перед записью в файл. Он используется так:

  sed '1d' file.txt |  файл sponge.txt  

Улучшите этот ответ
отредактировано 16 октября 2013 в 0:58
ответил 16 октября 2013 в 0:43
добавить комментарий |

Также обратите внимание на sponge из moreutils . sponge впитывает данные из стандартного ввода до тех пор, пока конец записи стандартного ввода не закроется перед записью в файл. Он используется так:

  sed '1d' file.txt |  файл sponge.txt  

9

ex можно использовать для редактирования на месте , которое не требует временного файла

   ex -c ': 1d' -c ': wq' file.txt  

Улучшите этот ответ
отредактировано 5 декабря 2013 года в 16:08
ответил 16 октября 2013 в 1:03
  • 2
    ex использует временный файл. strace -e open ex -c ': 1d' -c ': wq' foo . ex усекает исходный файл временным файлом, тогда как параметр -i GNU sed заменяет оригинал временным файлом. Я не уверен, как работает sed BSD. — llua 05 дек. ’13 в 16:03
  • @llua, вы правы. Я тоже это заметил, но позже — iruvar 5 дек. ’13 в 16:06
добавить комментарий |

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

  ex -c ': 1d' -c ': wq' file. txt  

5

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

  ex -s -c '1d | x' file.txt  
  1. 1 найти первую строку

  2. d удалить

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

Улучшить этот ответ
отредактировал 11 декабря 2018 в 23:07
ответил 11 апр. ’16 в 0:01
добавить комментарий |

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

  ex -s -c '  1d | x 'file.txt  
  1. 1 найти первую строку

  2. d удалить

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


4

Самый короткий и простой способ удалить первую строку из файла с помощью sed :

  $ sed -i -n  -e '2, $ p' file.txt  

Улучшите этот ответ
ответил 13 дек. ’16 в 9:55
добавить комментарий |

Самый короткий и простой способ удалить первую строку из файла с помощью sed :

  $ sed -i -n -e '2, $ p' file.txt  

0

Эта команда удалит 1 строку и сохранит ее как «file.txt».

   sed '1d' file.txt>/tmp/file.txt && mv/tmp/file.txt file.txt ||  rm -f/tmp/file.txt  

Улучшите этот ответ
отредактировано 8 октября 2014 г. в 1:59
Сообщество ♦
1
ответил 21 октября 2013 в 07:53
добавить комментарий |

Эта команда удалит 1 строку и сохранит ее как «file.txt».

  файл sed '1d'. txt>/tmp/file.txt && mv/tmp/file.txt file.txt ||  rm -f/tmp/file.txt  

0

Для этого можно использовать vim:

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

Улучшите этот ответ
ответил 17 окт. 2017 в 14:28
добавить комментарий |

Для этого можно использовать vim:

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

0

Чтобы удалить определенную строку в файле:

  1. Удалить первую строку
      sed '1d  'file  
  2. Удалить первую и третью строку
      файл sed' 1d3d ' 

Чтобы удалить символ в строке

  1. Удалить первые два символа в строке
      sed 's/^..//' file  
  2. Удалить последние два chrecter в строке
       sed 's/..$//' file  
  3. Удалить пустую строку
      sed '/^ $/d' file  
Улучшите этот ответ

отредактировано 13 мая ’20 в 7:20
AdminBee
10.3k55 золотых значков2424 серебряных плохих ges3737 бронзовые значки
ответ дан ges3737 22 окт. в 17:30
добавить комментарий |

Чтобы удалить определенную строку в файле:

  1. Удалить первую строку
      файл sed '1d  
  2. Удалить первую и третью строку
      файл sed '1d3d'  

Чтобы удалить символ в строке

  1. Удалить первые две диаграммы в файле lin
      sed/^..//' 
  2. Удалить два последних символа в строке
      sed 's/..$//' file  
  3. Удалить пустую строку
      файл sed '/^ $/d'  

Оцените статью
logicle.ru
Добавить комментарий