Ищите много разных строк в разных лог файлах?
У меня есть список файлов, которые пропали где-то в нашей системе на работе. У меня также есть папка, содержащая 41 лог-файл с добавлением до 46 МБ, в котором, я надеюсь, есть записи, относящиеся к отсутствующим файлам. Как я могу grep эти файлы журнала для любого значения в моем списке?
Список структурирован как один файл на строку без расширения файла. Журналы, кажется, имеют структуру, но я пока не совсем знаком с этой структурой. Он содержит имена файлов и пути, а также то, что с ним было сделано.
я знаю что могу cat *
все файлы журнала и передать его grep
, Я, вероятно, буду использовать -A
а также -B
чтобы получить небольшой контекст из файлов журнала, когда имя найдено. Я использую GnuWin32 на окнах, чтобы я мог соединить это с Powershell, но я думаю, что для этого потребуется, чтобы одно имя файла выделило все 46 МБ, а когда я перейду к следующему имени файла, я начну заново. У меня в списке 1830 файлов, поэтому, если мне придется начинать все сначала, я буду читать 46 МБ столько раз, что буду иметь дело с ГБ повторяющихся данных. Это кажется неэффективным.
Я полагаю, я мог бы создать большое регулярное выражение из файлов 1830 года или собрать вместе и запустить его один раз для журналов, но возможно ли это? Регулярное выражение будет почти 30 КБ (1830 файлов * средняя длина имени файла около 16 символов = 29280 байт, не говоря уже о еще 1830 байтах символов канала).
Изменить: Вот что я делаю сейчас, когда я нахожусь в папке журналов, и список находится на одну папку назад:
$logs = gc *
$notfound = gc ../notfound.txt
$logs | % { $i = 0; while ($i -lt $notfound.Count) { if ($_ -contains $notfound[$i]) { echo $_ }; $i++; } } | out-file C:\discovered.txt
Это полностью PowerShell. Я готов использовать любой инструмент, чтобы ускорить это, потому что сейчас во всех файлах журнала есть 550991 строка и 1830 имен файлов, поэтому этот подход делает 1 008 313 530 сравнений. Это все в памяти, так что, по крайней мере, у меня нет дискового ввода-вывода, замедляющего меня. Я мог бы вырваться из while
если if
становится правдой, но я все еще собираюсь сделать так много сравнений, я не уверен, что оптимизация действительно принесет пользу. Это уже работает в течение получаса. Я в порядке с переписыванием моего подхода от линии 1, если я могу сделать это прежде, чем я уеду домой на выходные.
1 ответ
Было бы эффективнее извлечь имена файлов из журналов с помощью регулярного выражения и посмотреть, есть ли каждое из них в вашем списке. Это может выглядеть примерно так:
$notfound = gc ../notfound.txt
gc * |
select-string -AllMatches '\\(?<filename>[^\\]+)\.txt' |
select -ExpandProperty Matches |
% { $_.Groups['filename'].Value } |
? { $notfound -contains $_ } |
out-file C:\discovered.txt
Я ищу файлы, которые выглядят как "\something.txt". Вам придется изменить это.
Если он все еще слишком медленный, а ваш необнаруженный список очень большой, то, возможно, было бы более эффективно загрузить его в.Net HashSet, но я бы не стал этого делать без необходимости.