我是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
我试图研究如何打印到新行,以及替换正则表达式查询中的字符串以消除/添加所需的细节。
感谢您的回应。
答案 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