我是Powershell的新手,我已经创建了一个脚本来读取日志文件,并将文件从同一行的部分字符串输出到该文件。
我也是regex的新手,所以到目前为止,这是一条相对僵硬的曲线!
基于这篇文章,我决定在同样的基础上编写一个脚本。
$input_path = 'C:UsersXXXXXXXXDesktopSample.log'
$output_file = 'C:UsersXXXXXXXXDesktopOuput.log'
if ($regex = 'b([1-9]|([012][0-9])|(3[01]))/([0]{0,1}[1/9]|1[012])/dddd [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
我试图研究如何打印到新行,以及替换正则表达式查询中的字符串,以消除/添加所需的详细信息。
感谢您的回复。
我可能更喜欢使用字符串操作,但regex通常更快。[grin]
假设$InStuff
包含您发布的两行,这将获取您似乎想要的部分。。。
$Instuff[0] -match '^(?<TimeStamp>.+?) [AM|PM].+[Rcv|Snd] (?<IP>.+?)s{2,}.+] (?<RecordType>.+?)s{2,}(d+)(?<Domain>.+?)(d{1,})(?<TLD>.+?)(d{1,})$'
则自动变量CCD_ 2将具有准备使用的各种命名匹配。这是你发布的第一行的输出。。。
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
或任何其他属性名称来处理这些匹配。
由于它是被请求的,这里是带有"保存到文件"的代码的完整版本。。。[grin]
# 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:TEMPCleanedVersion.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
基于您的新样本数据,此脚本使用命名捕获组增强RE:编辑:更改RegEx以获取所有域级别
## Q:Test20181027SO_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