Вывести на ту же / отдельную строку и заменить строки регулярных выражений - PullRequest
0 голосов
/ 29 октября 2018

Я новичок в Powershell, и я создал скрипт для чтения файла журнала и вывода файла только из частей строки в той же строке в файл.

Я также новичок в регулярных выражениях, так что пока это была довольно жесткая кривая!

На основании этой статьи Я решил создать сценарий на той же основе.

$input_path = 'C:\Users\XXXXXXXX\Desktop\Sample.log'
$output_file = 'C:\Users\XXXXXXXX\Desktop\Ouput.log'

if ($regex = '\b([1-9]|([012][0-9])|(3[01]))/([0]{0,1}[1/9]|1[012])/\d\d\d\d [012]{0,1}[0-9]:[0-6][0-9]:[0-6][0-9]\b|\b(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\b|]\s(\w+)|\(\d*\)\D+\(2\)\D+\(2\)\w+|\(\d*\)\D+\([1-5]\)\w+') {select-string -Path $input_path -Pattern $regex -AllMatches | % { $_.Matches } | % { $_.Value } > $output_file}

Журнал образцов

25/10/2018 16:48:23 PM 0710 PACKET  0000000028FB94C0 UDP  Rcv 69.160.33.71    8857  Q [0080       NOERROR] A      (16)offeringsmislead(3)com(0)
25/10/2018 16:48:23 AM 0714 PACKET  000000002CC599A0 UDP  Snd 8.8.8.8         3434  Q [1001   D   NOERROR] A      (10)controltag(3)net(0)

С помощью скрипта, который я исказил, мне удалось записать следующее в отдельный файл:

Журнал токового выхода: (это в отдельных строках)

25/10/2018 16:48:23
69.160.33.71
] A
(16)offeringsmislead(3)com
25/10/2018 16:48:23
8.8.8.8
] A
(10)controltag(3)net

Я хотел бы получить желаемый результат:

25/10/2018 16:48:23 69.160.33.71 A offeringsmislead.com
25/10/2018 16:48:23 8.8.8.8 A controltag.net

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

Ценю ваши ответы.

Ответы [ 2 ]

0 голосов
/ 29 октября 2018

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

Предполагается, что $InStuff содержит две строки, которые вы опубликовали, это будет захватывать части, которые вы, кажется, хотите ...

$Instuff[0] -match '^(?<TimeStamp>.+?) [AM|PM].+[Rcv|Snd] (?<IP>.+?)\s{2,}.+] (?<RecordType>.+?)\s{2,}\(\d+\)(?<Domain>.+?)\(\d{1,}\)(?<TLD>.+?)\(\d{1,}\)$'

тогда автоматическая переменная $Matches будет иметь различные именованные совпадения, готовые к использованию. вот вывод для 1-й строки, которую вы разместили ...

Name                           Value                                                                              
----                           -----
Domain                         offeringsmislead
TLD                            com
IP                             69.160.33.71
TimeStamp                      25/10/2018 16:48:23
RecordType                     A
0                              25/10/2018 16:48:23 PM 0710 [*...snip...*]

Вы можете обратиться к этим совпадениям через $Matches.Domain или любое другое имя свойства.


с момента запроса, вот полная версия кода с надписью "сохранить в файл" ... [ ухмылка ]

# fake reading in a file
#    in real life, use Get-Content
$InStuff = @'
25/10/2018 16:48:23 PM 0710 PACKET  0000000028FB94C0 UDP  Rcv 69.160.33.71    8857  Q [0080       NOERROR] A      (16)offeringsmislead(3)com(0)
25/10/2018 16:48:23 AM 0714 PACKET  000000002CC599A0 UDP  Snd 8.8.8.8         3434  Q [1001   D   NOERROR] A      (10)controltag(3)net(0)
'@ -split [environment]::NewLine

$NamedRegex = '^(?<TimeStamp>.+?) [AM|PM].+[Rcv|Snd] (?<IP>.+?)\s{2,}.+] (?<RecordType>.+?)\s{2,}\(\d+\)(?<Domain>.+?)\(\d{1,}\)(?<TLD>.+?)\(\d{1,}\)$'
$CleanedFileName = "$env:TEMP\CleanedVersion.log"

$Results = foreach ($IS_Item in $InStuff)
    {
    # supress unwanted False/True output
    $Null = $IS_Item -match $NamedRegex
    # join the named matches with a single space
    #    plus, join the Domain & TLD with a dot
    #    if you want things padded to a constant colum width, use `.PadLeft()`
    $Matches.TimeStamp, $Matches.IP, $Matches.RecordType, ($Matches.Domain, $Matches.TLD -join '.') -join ' '
    }

# on screen output
$Results

# send to text file
$Results |
    Set-Content -LiteralPath $CleanedFileName

вывод на экран ...

25/10/2018 16:48:23 69.160.33.71 A offeringsmislead.com
25/10/2018 16:48:23 8.8.8.8 A controltag.net

содержимое "cleanedversion.log" ...

25/10/2018 16:48:23 69.160.33.71 A offeringsmislead.com
25/10/2018 16:48:23 8.8.8.8 A controltag.net
0 голосов
/ 29 октября 2018

На основе ваших новых примеров данных этот скрипт с расширенным RE с использованием именованных групп захвата: РЕДАКТИРОВАТЬ: изменил RegEx, чтобы получить все уровни домена.

## Q:\Test\2018\10\27\SO_53047308.ps1
$input_path  = '.\Sample.log'
$output_file = '.\Output.log'

$RE = [regex]"^(?<dt>[0-9\/: ]{16,19}).*?(Rcv |Snd )(?<IP>(\d+\.){3}\d+)[^\]]+\] (?<RecType>[^ ]+) +(?<DOM>.*)$"

Get-Content $input_path | ForEach-Object {
  if ($_ -match $RE){
    "{0} {1} {2} {3}" -f $Matches.DT.Trim(),$Matches.IP,$Matches.RecType,$($Matches.Dom -replace '\(\d+\)','.').Trim('.')
  }
} | Set-Content $output_file

выведет:

> gc .\Output.log
25/10/2018 16:48:23 69.160.33.71 A offeringsmislead.com
25/10/2018 16:48:23 8.8.8.8 A controltag.net

Чтобы лучше объяснить, что делает RE +(?<DOM>.*)$:

  • + соответствует всем пробелам, следующим за типом записи
  • (?<DOM>.*)$ захватывает все .* до конца строки $ в указанной группе захвата DOM
    (16)offeringsmislead(3)com(0)
    (10)controltag(3)net(0)
  • $($Matches.Dom -replace '\(\d+\)','.') меняет (99) на . хотя бы одну цифру, столько же, сколько присутствует.
    .offeringsmislead.com.
    .controltag.net.
  • .Trim('.') полоски ведущих / конечных точек
    offeringsmislead.com
    controltag.net
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...