Найти и заменить несколько строк в огромном текстовом файле - PullRequest
2 голосов
/ 22 апреля 2011

У меня есть огромный лог-файл (почти 6 ГБ) игрового сервера, заполненный миллионами ошибок (сотни были вызваны каждую секунду в то время), кроме полезных записей, которые нужно хранить.Я хотел бы удалить все строки, включая ошибку, при этом в них отображаются сообщения чата или другая информация.

Однако я не могу просто удалить строки, которые хочу сбросить, поскольку сообщения об ошибкахне всегда одинаковы и всегда требуют различного количества строк.Короче говоря, я просто не могу определить, какие строки содержат ошибку.Мне нужно регулярное выражение, чтобы сделать это.Я искал программу, которая соответствует моим целям.Я еще не нашел, хотя.Например, sed (потоковый редактор) может выполнить такую ​​работу, так как ему не потребуется слишком много ресурсов для обработки такого огромного файла.Однако он не поддерживает поиск и замену в несколько строк.

Следовательно, существует ли программа, которая поддерживает поиск и замену регулярных выражений в больших текстовых файлах в несколько строк?Или рекомендуется написать собственный сценарий для выполнения этой работы?

Файл журнала выглядит следующим образом:

2011-03-02 01:43:00 [INFO] <admin> CraftBook is causing errors. 
2011-03-02 01:43:01 [SEVERE] Could not pass event REDSTONE_CHANGE to CraftBookMechanisms
java.lang.NoSuchMethodError: com.sk89q.worldedit.blocks.BlockType.isRedstoneBlock(I)Z
    at com.sk89q.craftbook.bukkit.MechanicListenerAdapter$MechanicBlockListener.onBlockRedstoneChange(MechanicListenerAdapter.java:174)
    at net.minecraft.server.BlockButton.a(BlockButton.java:170)
    at net.minecraft.server.ItemInWorldManager.a(ItemInWorldManager.java:160)
    at net.minecraft.server.NetServerHandler.a(NetServerHandler.java:482)
    at net.minecraft.server.Packet15Place.a(SourceFile:57)
    at net.minecraft.server.NetworkManager.a(SourceFile:230)
    at net.minecraft.server.NetServerHandler.a(NetServerHandler.java:75)
    at net.minecraft.server.NetworkListenThread.a(SourceFile:100)
    at net.minecraft.server.MinecraftServer.h(MinecraftServer.java:357)
    at net.minecraft.server.MinecraftServer.run(MinecraftServer.java:272)
    at net.minecraft.server.ThreadServerApplication.run(SourceFile:366)
2011-03-02 01:43:01 [INFO] <admin> Is it working yet? 
2011-03-02 01:43:01 [INFO] <admin> Not really. 
2011-03-02 01:43:01 [SEVERE] Could not pass event REDSTONE_CHANGE to CraftBookMechanisms
java.lang.NoSuchMethodError: com.sk89q.worldedit.blocks.BlockType.isRedstoneBlock(I)Z
    at com.sk89q.craftbook.bukkit.MechanicListenerAdapter$MechanicBlockListener.onBlockRedstoneChange(MechanicListenerAdapter.java:174)
    at net.minecraft.server.MinecraftServer.h(MinecraftServer.java:348)
    at net.minecraft.server.MinecraftServer.run(MinecraftServer.java:272)
    at net.minecraft.server.ThreadServerApplication.run(SourceFile:366)
2011-03-02 01:43:02 [INFO] <admin> I hope we find a solution as soon as ever possible. 

Желаемый результат будет следующим:

2011-03-02 01:43:00 [INFO] <admin> CraftBook is causing errors.
2011-03-02 01:43:01 [INFO] <admin> Is it working yet? 
2011-03-02 01:43:01 [INFO] <admin> Not really. 
2011-03-02 01:43:02 [INFO] <admin> I hope we find a solution as soon as ever possible.

Как видите, файл журнала снова и снова содержит одну и ту же ошибку.Даже если он всегда начинается с даты и времени, за которыми следует [SEVERE] Не удалось передать событие REDSTONE_CHANGE в CraftBookMechanisms и заканчивается в net.minecraft.server.ThreadServerApplication.run (SourceFile: 366) , сообщение об ошибке между ними отличается каждый раз.Вот почему я не могу просто заменить сообщение об ошибке пустой строкой.

Существует ли регулярное выражение, которое могло бы помочь мне избавиться от всех строк, содержащих ошибку, но сохранить оставшиеся строки?Таким образом, размер моего файла журнала уменьшится до 50 МБ, как это было до того, как все эти ошибки были вызваны моим сервером из-за сломанного плагина.

Ответы [ 2 ]

2 голосов
/ 23 апреля 2011

Этот скрипт Python делает один проход через файл журнала, считанный из стандартного ввода, и печатает отфильтрованные сообщения журнала в стандартный вывод.

Используется регулярное выражение для сопоставления строк, отмечающих начало сообщения журнала (например, строки, начинающейся с 2011-03-02 01:43:00 [).

Если строка, которая начинается с сообщения журнала, содержит [SEVERE] Could not pass event REDSTONE_CHANGE to CraftBookMechanisms, сценарий отбрасывает все строки между этой строкой и строкой, содержащей начало следующего сообщения журнала. В противном случае он выводит строку. Вы можете думать об этом как о конечном автомате с двумя состояниями, которые соответствуют тому, пропускает ли сценарий строки или выводит строки.

import sys
import re

START_OF_MESSAGE_RE = r"^\d{4}-\d{2}-\d{2} \d{2}:\d{2}:\d{2}"
ERROR_RE = START_OF_MESSAGE_RE + r' \[SEVERE\] Could not pass event REDSTONE_CHANGE to CraftBookMechanisms$'
skip_until_next_message = False

for line in sys.stdin:
    line = line.rstrip()
    if re.match(START_OF_MESSAGE_RE, line):
        if re.match(ERROR_RE, line):
            skip_until_next_message = True
        else:
            skip_until_next_message = False
    if not skip_until_next_message:
        print line

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

2011-03-02 01:43:00 [INFO] <admin> CraftBook is causing errors. 
2011-03-02 01:43:01 [SEVERE] Could not pass event REDSTONE_CHANGE to CraftBookMechanisms
java.lang.NoSuchMethodError: com.sk89q.worldedit.blocks.BlockType.isRedstoneBlock(I)Z
    at com.sk89q.craftbook.bukkit.MechanicListenerAdapter$MechanicBlockListener.onBlockRedstoneChange(MechanicListenerAdapter.java:174)
    at net.minecraft.server.BlockButton.a(BlockButton.java:170)
    at net.minecraft.server.ItemInWorldManager.a(ItemInWorldManager.java:160)
    at net.minecraft.server.NetServerHandler.a(NetServerHandler.java:482)
    at net.minecraft.server.Packet15Place.a(SourceFile:57)
    at net.minecraft.server.NetworkManager.a(SourceFile:230)
    at net.minecraft.server.NetServerHandler.a(NetServerHandler.java:75)
    at net.minecraft.server.NetworkListenThread.a(SourceFile:100)
    [SEVERE] Could not pass event REDSTONE_CHANGE to CraftBookMechanisms
    at net.minecraft.server.MinecraftServer.h(MinecraftServer.java:357)
    at net.minecraft.server.MinecraftServer.run(MinecraftServer.java:272)
    at net.minecraft.server.ThreadServerApplication.run(SourceFile:366)
2011-03-02 01:43:01 [INFO] <admin> Is it working yet? 
2011-03-02 01:43:01 [INFO] <admin> Not really. 
2011-03-02 01:43:01 [SEVERE] Could not pass event REDSTONE_CHANGE to CraftBookMechanisms
java.lang.NoSuchMethodError: com.sk89q.worldedit.blocks.BlockType.isRedstoneBlock(I)Z
    at com.sk89q.craftbook.bukkit.MechanicListenerAdapter$MechanicBlockListener.onBlockRedstoneChange(MechanicListenerAdapter.java:174)
    at net.minecraft.server.MinecraftServer.h(MinecraftServer.java:348)
    at net.minecraft.server.MinecraftServer.run(MinecraftServer.java:272)
    at net.minecraft.server.ThreadServerApplication.run(SourceFile:366)
2011-03-02 01:43:02 [INFO] <admin> I hope we find a solution as soon as ever possible. 
2011-03-02 01:43:01 [SEVERE] Another multi
line
log
message
2011-03-02 01:43:01 [INFO] <admin> Here's the error: [SEVERE] Could not pass event REDSTONE_CHANGE to CraftBookMechanisms

А вот и вывод:

$ python minecraftlog.py < minecraft.log 
2011-03-02 01:43:00 [INFO] <admin> CraftBook is causing errors.
2011-03-02 01:43:01 [INFO] <admin> Is it working yet?
2011-03-02 01:43:01 [INFO] <admin> Not really.
2011-03-02 01:43:02 [INFO] <admin> I hope we find a solution as soon as ever possible.
2011-03-02 01:43:01 [SEVERE] Another multi
line
log
message
2011-03-02 01:43:01 [INFO] <admin> Here's the error: [SEVERE] Could not pass event REDSTONE_CHANGE to CraftBookMechanisms
0 голосов
/ 22 апреля 2011

Кажется, лучший подход - это сопоставить строки, которые вы хотите сохранить, косвенно "удаляя" строки, которые вам не нужны:

Подойдет следующий скрипт на Perl:

while (<>) {
  next unless /^\d{4}-\d{2}-\d{2}\s\d{2}:\d{2}:\d{2}\s\[INFO\]/;
  print;
}
...