打印到相同/单独的行并替换正则表达式字符串

时间:2018-10-29 14:09:48

标签: regex powershell

我是Powershell的新手,我创建了一个脚本来读取日志文件,并将文件仅从同一行中的部分字符串输出到文件。

我也是regex的新手,所以到目前为止这是一条相对较硬的曲线!

基于this article,我决定在相同的基础上编写脚本。

$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 :(得分:1)

基于您的新样本数据,该脚本具有使用命名捕获组的增强型RE: 编辑:更改了正则表达式以获取所有域级别。

## 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

答案 1 :(得分:1)

我可能更喜欢使用字符串操作,但是正则表达式 通常更快。 [咧嘴]

假设$InStuff包含您发布的两行,这将获取您似乎想要的部分...

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

然后,自动变量$Matches将具有各种已命名的匹配项可供使用。这是您发布的第一行的输出...

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