
У меня есть список файлов, которые где-то пропали в нашей системе на работе. У меня также есть папка, полная 41 файла журнала, в сумме до 46 МБ, которые, как я надеюсь, содержат записи журнала, относящиеся к пропавшим файлам. Как мне выполнить grep этих файлов журнала на предмет любого значения в моем списке?
Список структурирован как один файл на строку без расширения файла. Журналы, похоже, имеют структуру, но я пока не совсем с ней знаком. Он содержит имена файлов и пути, а также то, что с ними было сделано.
Я знаю, что могу cat *
все файлы журналов и передать их в grep
. Я, вероятно, буду использовать -A
и , -B
чтобы получить немного контекста из файлов журналов, когда имя найдено. Я использую GnuWin32 в Windows, поэтому я мог бы связать это с 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". Вам придется это изменить.
Если он все еще слишком медленный, а ваш список notfound очень большой, то, возможно, более эффективным будет загрузить его в .Net HashSet, но я бы не советовал делать этого без крайней необходимости.