2015-12-22 4 views
0

У меня есть журнал сборки, из которого я хочу извлечь некоторый контент. Я хочу извлечь [xxxxcontentxxxx] из файла журнала с указанием имени системы, если таковой имеется.Извлечь контент между двумя словами

input.txt:

150755: CMDLINE=omake System1 
150758: Subsystem Start: Tue Dec 22 03:33:06 2015 1450726386 
[xxxxcontentxxxx] 
151251: Subsystem End: Tue Dec 22 03:35:00 2015 1450726500 
151255: CMDLINE=omake System2 
151258: Subsystem Start: Tue Dec 22 03:35:00 2015 1450726500 
151668: Subsystem End: Tue Dec 22 03:36:28 2015 1450726588 
151672: CMDLINE=omake System3 
151675: Subsystem Start: Tue Dec 22 03:36:29 2015 1450726589 
[xxxxcontentxxxx] 
152020: Subsystem End: Tue Dec 22 03:38:14 2015 1450726694 
152024: CMDLINE=omake System4 
152027: Subsystem Start: Tue Dec 22 03:38:15 2015 1450726695 
[xxxxcontentxxxx] 
152294: Subsystem End: Tue Dec 22 03:39:12 2015 1450726752 
152298: CMDLINE=omake System5 
152301: Subsystem Start: Tue Dec 22 03:39:12 2015 1450726752 
[xxxxcontentxxxx] 
152558: Subsystem End: Tue Dec 22 03:40:18 2015 1450726818 

Например, я хочу, чтобы извлечь для System2, System3 и System4. Вывод должен быть сохранен в виде файла в следующем формате:

Примечание: System2 пропускается, поскольку он не содержит [xxxxcontentxxxx]

output.txt:

151672: CMDLINE=omake System3 
151675: Subsystem Start: Tue Dec 22 03:36:29 2015 1450726589 
[xxxxcontentxxxx] 
152020: Subsystem End: Tue Dec 22 03:38:14 2015 1450726694 
152024: CMDLINE=omake System4 
152027: Subsystem Start: Tue Dec 22 03:38:15 2015 1450726695 
[xxxxcontentxxxx] 
152294: Subsystem End: Tue Dec 22 03:39:12 2015 1450726752 

Как могу ли я добиться этого с помощью PowerShell?

Вот что у меня есть. Конечно, есть более элегантный способ достижения этой цели:

$reader = [System.IO.File]::OpenText("C:\log.txt") 
try { 
    $startPrinting = $false 
    for (;;) { 
     $line = $reader.ReadLine() 
     if ($line -eq $null) { break } 
     if ($line.Split(' ').Contains("System2") -or 
      $line.Split(' ').Contains("System3") -or 
      $line.Split(' ').Contains("System4") 
      ) { 
      $startPrinting = $true 

     } 

     if ($startPrinting) { 
      Write-Host $line 
     } 

     if ($line.split(' ').Contains('End:')) { 
      $startPrinting = $false 
     } 
    } 
} finally { 
    $reader.Close() 
} 

ответ

0

Вы можете, например, использовать switch заявление, например:

$systems = 'System2', 'System3', 'System4' 

$reader = [IO.File]::OpenText('.\Documents\test.txt') 

while ($line = $reader.ReadLine()) { 
    switch -regex ($line) { 
    'CMDLINE=omake (\S+)' { 
     $systemName = $matches[1] 
     $msg = @($line) 
    } 
    'Subsystem End' { 
     if ($systems -contains $systemName) { 
     if ($msg.Count -gt 3) { 
      $msg -join "`r`n" 
     } else { 
      "Note: $systemName is skipped because it doesn't have content." 
     } 
     } 
    } 
    default { $msg += $line } 
    } 
} 

$reader.Close() 

Это, конечно, совершенно неполированный, как он предполагает, что ваш входной файл всегда начинается с линии CMDLINE и заканчивается линией Subsystem End. Но это должно дать вам общую идею.

+0

Спасибо Ansgar. Ваше решение, безусловно, намного опрятно. Тем не менее, он отображает журналы из всех систем. Фильтры не применяются для сужения журнала до конкретных систем. Любой способ применить такую ​​фильтрацию? –

+0

Вывод, только если имя системы указано в списке имен систем. См. Обновленный ответ. –

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