Соответствие шаблону Powershell для нескольких последних записей и имени файла для каждого результата - PullRequest
1 голос
/ 14 января 2020

Я новичок в Powershell и мне нужна информация или руководство по следующему сценарию. У меня есть несколько файлов в папке, и я хочу, чтобы пользователь Powershell посмотрел на них, и если им исполнился один день, извлеките последние несколько строк, пока он не увидит заданный шаблон c. Вывод должен быть в текстовом файле, и я хочу включить имя файла для каждого результата.

Я смог написать скрипт для доступа к файлам, извлечь последние 2 строки и поместить его в выходной файл. Я не знаю, как сделать сопоставление с шаблоном и заставить скрипт только захватывать строки, пока он не увидит шаблон "--- (S3B"), а также включить имя файла для каждого результата в выходной файл. Любая помощь приветствуется.

Пример файлов и данных

Файл 1: ABC_1.txt

aaaaaa

bbbbbb

--- (s3B

cccccc

dddddd

--- (s3B

eeeee

fffff

Файл 2: ABC_2.txt

ggg

aaaaaa

--- (s3B

oooooo

ABC_3.txt

ppppp

--- (s3B

aaaaaa

Файл 3: XYZ_1.txt

гггггг

--- (s3B

rrrrrrr

cccccc

--- (s3B

sssssss

qqqqqqq

Желаемый вывод в файле

ABC_1.txt

cccccc

dddddd

ABC_2.txt

oooooo

ABC_3.txt

aaaaaa

XYZ_1.txt

sssssss

qqqqqqq

Пример Скрипт, который просматривает x количество дней на основе моего ввода и захватывает 2 строки , Как я могу заставить его захватить несколько последних строк и остановиться на шаблоне --- (s3B, а также включить имя файла для каждого результата в мой выходной файл.

$path = "C:\Test"
$files = Get-ChildItem $path -recurse -Include *.txt | Where-Object {$_.CreationTime -gt "$date" } 
$date = (Get-Date).AddDays(-1).ToString("MM-dd-yyyy")

foreach ($file in $files) {get-content $file | select  -Last 2  |out-file $Results -append }

$Results = "C:\Test\$($file.name).txt"

Пример результата из сценария, созданного в выходном файле

cccccc

dddddd

--- (s3B

oooooo

--- (s3B

aaaaaa

sssssss

qqqqqqq

Ответы [ 2 ]

1 голос
/ 14 января 2020

Я тоже думал о Select-String, но я не знаю, как сфокусировать его только на последних 2 строках. Сначала вы можете получить Get-Content и передать его в Select-String, но потом я не уверен, как вы прекратите вывод, когда совпадение найдено. -Контекст даст окружающие линии независимо. Я работал над этим нелегко, но я надеюсь, что ошибаюсь (ухмыляется):

$path = "C:\Temp"
$date = (Get-Date).AddDays(-1)
$files = Get-ChildItem $path -recurse -Include *.txt | Where-Object { $_.CreationTime -gt $date }
$Pattern = "Server Failures"
$OutputFile = "C:\Temp\SomeOutput.txt"

foreach ($file in $files)
{    
    $Results = [System.Collections.ArrayList]@()

    :Inner ForEach( $Line in (get-content $file -tail 2) ) 
    {
        If( $Line -match $Pattern )
        {
            [Void]$Results.Add($Line)
            Break Inner
        }
        Else
        {
            [Void]$Results.Add($Line)
        } 
    }

    If( $Results )
    {
        ( $File.Name + ":") | Out-File $OutputFile -Append
        $Results | Out-File $OutputFile -Append
    }
}

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

Дайте мне знать, что вы думаете. Если вам нужно разобраться, как это работает и т. Д.

0 голосов
/ 14 января 2020

Использование Select-String с переключателем -Context, вероятно, путь к go. Пример ниже, но не проверен:

$path = "C:\Test"
$date = (Get-Date).Date.AddDays(-1)
Get-ChildItem $path -recurse -Include *.txt | Where-Object {$_.CreationTime -gt $date} | Select-String -Pattern '---(S3B' -Context 2, 0 | % {
    $f = $_.Filename
    $_.Context.PreContext | % {"{0} -> {1}" -f $f, $_}
} | Out-File $Results 
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...