2015-08-25 6 views
3

Я фильтрую большой файл журнала веб-доступа и создаю около десятка меньших в зависимости от соответствия регулярному выражению. Поскольку у меня мало опыта работы с регулярным выражением, я бы хотел выяснить, как оптимизировать шаблоны для повышения производительности.Оптимизировать соответствие RegEx в PowerShell

Источник отформатирован следующим образом:

2015-06-14 00:00:06 38.75.53.205 - HTTP 10.250.35.69 80 GET /en/process/dsa/policy/wbss/wbss_current/wbss2013/Wbss13.pdf - 206 299 16722 0 HTTP (etc) 

или

2015-06-13 00:00:31 1.22.55.170 - HTTP 157.150.186.68 80 GET /esd/sddev/enable/compl.htm - 200 396 23040 0 HTTP/1.1 Mozilla (etc) 

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

dsq = "(/esd/sddev/| /creative/)" 
dpq = "/dsa/policy/" 
pop = "(^((?! /popq/ /caster/(dsa/(policy|qsc|qlation))|(esd/(fed|cdq|qaccount|sddev|creative|forums/rdev))).)*$)" 

Первые два надеется соответствовать указанной модели, в то время как «поп» должна соответствовать все, кроме указанных моделей.

Это работает так, как есть, но поскольку мои файлы журналов имеют тенденцию к довольно большой (1 ГБ и больше), и у меня есть 12 разных шаблонов, чтобы соответствовать, я надеялся, что может быть способ улучшить производительность этих шаблонов ,

Что касается использования, у меня есть следующий код, где $profile является одним из тех, которые перечислены выше (они находятся в хэш-таблице, и цикл I через них отдельно):

Get-Content $sourcefile -ReadCount 5000 | 
ForEach { $_ -match $profile | Add-Content targetfile } 

Спасибо всем за любое понимание!

+0

[ConvertFrom-String] (http://blogs.msdn.com/b/powershell/archive/2014/10/31/convertfrom-string-example-based-text-parsing.aspx) может помочь – StegMan

+0

Я думаю что StegMan говорит, что его предложение состоит в том, чтобы взять каждую строку и преобразовать ее в объект PowerShell, чтобы вы могли делать более целенаправленные поиски данных. – Matt

+0

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

ответ

3

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

Get-Content $sourcefile -ReadCount 5000 | ForEach { 
    switch -regex ($_) { 
     $dsq {$chosenPath = "file1"; continue} 
     $dpq {$chosenPath = "file2"; continue} 
     $pop {$chosenPath = "file3"; continue} 
     default {} 
    } 

    # If no path is set they we skip this step. 
    If($chosenPath){$_ | Add-Content $chosenPath} 
} 

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

Вы можете переписать это с помощью add-content для каждого матча, но я пытался прекратить повторять аналогичный код. Если вы удалили его и вернули во все add-content, вы могли бы удалить логику $null, которую я добавил.

Regex эффективность

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

$pop = "/popq/ /caster/(dsa/(policy|qsc|qlation))|esd/(fed|cdq|qaccount|sddev|creative|forums/rdev))" 
Get-Content $sourcefile -ReadCount 5000 | 
    ForEach { $_ -notmatch $pop | Add-Content targetfile } 

Как примечание стороны, я бы ожидать, что вам потребуется второй цикл там, чтобы вырваться из массива 5000 пунктов?

Get-Content $sourcefile -ReadCount 5000 | 
ForEach { $_ | ForEach{ $_ -match $profile | Add-Content targetfile }} 

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

+0

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

+0

@ PredragVasić Я следую вашему комментарию до последнего предложения. Он будет добавляться к выходным файлам, определяемым совпадением во время каждого прохода. – Matt

+0

, что касается '-ReadCount 5000', на основе моих результатов линия выполняет регулярное выражение на 5000 строк за раз, по очереди. Результат из этого кода кажется правильным, с выходными файлами, содержащими более 400 тыс. Согласованных строк из источника с более чем 700 тыс. Строк. Когда я впервые получил код без '-ReadCount 5000', он работал навсегда. Кто-то еще предложил добавить его, и, по-видимому, он загружает 5000 строк в память за раз, делая его намного быстрее, вместо того, чтобы читать каждую строку из файла каждый раз, когда он выполняет совпадение. Вот как мне это объяснили, и результаты, похоже, подтверждают это. –

Смежные вопросы