我試圖從一個相當討厭的日志檔案中獲取額外的多個資料點(第一個、最后一個、ID 號)。
我有這個:
Get-Content c:\LOG\22JAN01.log | Out-String |
% {[Regex]::Matches($_, "(?<=FIRST:)((.|\n)*?)(?=LAST:)")} | % {$_.Value}
這在提取名字方面做得很好 - 但我還需要從同一行中獲取姓氏和 ID 號并將它們一起顯示“BOB SMITH 123456”
日志檔案的每一行如下所示:
第一:鮑勃最后:史密斯門:主入口 ID:123456 時間:2021 年 12 月 31 日,星期五 11:55:47 PM 事件:19002304
我希望輸出看起來像:
- 鮑勃·史密斯 123456
- 杰克瓊斯 029506
- 卡倫·卡彭特 6890298
到目前為止,我只能設法獲得所有的名字,而別無其他。感謝您為我指明正確方向的任何幫助!
uj5u.com熱心網友回復:
如果它們總是在同一條線上,我喜歡使用 switch 來閱讀它。
switch -Regex -File c:\LOG\22JAN01.log {
'FIRST:(\w ) LAST:(. ) DOOR. ID:(\d ) ' {
[PSCustomObject]@{
First = $matches[1]
Last = $matches[2]
ID = $matches[3]
}
}
}
示例日志輸出
First Last ID
----- ---- --
BOB SMITH 123456
JACK JONES 029506
KAREN KARPENTER 6890298
您可以將其捕獲到一個變數中,然后繼續使用您喜歡的物件。
$output = switch -Regex -File c:\LOG\22JAN01.log {
'FIRST:(\w ) LAST:(. ) DOOR. ID:(\d ) ' {
[PSCustomObject]@{
First = $matches[1]
Last = $matches[2]
ID = $matches[3]
}
}
}
$output | Out-GridView
$output | Export-Csv -Path c:\Log\parsed_log.log -NoTypeInformation
uj5u.com熱心網友回復:
您需要使用捕獲組()。
假設它FIRST總是在行的開頭(洗掉^if not),并且欄位名稱始終存在且順序相同,并且它們的值至少是一個字符長,您可以使用,例如:
$result = & {
$path = "c:\LOG\22JAN01.log";
$pattern = "^FIRST:(. ?) LAST:(. ?) DOOR:. ? ID:(\d )";
Select-String -Path $path -Pattern $pattern -AllMatches |
% {$_.Matches.Groups[1], $_.Matches.Groups[2], $_.Matches.Groups[3] -join " "}
}
. ?意味著匹配一個或多個除換行符之外的任何字符,在匹配模式中的內容之前盡可能少地匹配。[A-Z] 如果肯定會匹配所需的值,則可以使用更具限制性的內容。
uj5u.com熱心網友回復:
如果您可以假設每個欄位名稱僅由(英文)字母組成,[1]如FIRST,則可以使用將-replace運算子與ConvertFrom-StringDatacmdlet結合的通用解決方案:
# Sample array of input lines.
$inputLines =
'FIRST:BOB LAST:SMITH DOOR:MAIN ENTRANCE ID:123456 TIME:Friday, December 31, 2021 11:55:47 PM INCIDENT:19002304',
'FIRST:JACK LAST:JONES DOOR:SIDE ENTRANCE ID:123457 TIME:Friday, December 31, 2021 11:55:48 PM INCIDENT:19002305',
'FIRST:KAREN LAST:KARPENTER DOOR:BACK ENTRANCE ID:123458 TIME:Friday, December 31, 2021 11:55:49 PM INCIDENT:19002306'
$inputLines -replace '\b([a-z] ):', "`n`$1=" |
ConvertFrom-StringData |
ForEach-Object { $_.FIRST, $_.LAST, $_.ID -join ' ' }
對于每個輸入線路,所述
-replace操作中的每個欄位名稱-值對放置到它自己的線路,取代了分離器,:與=。生成的行塊被決議
ConvertFrom-StringData為表示每個輸入行的欄位的哈希表,允許按名稱方便地訪問欄位,例如.FIRST(PowerShell 允許您使用屬性訪問語法作為索引語法 sg的替代方法['FIRST'])。
輸出:
BOB SMITH 123456
JACK JONES 123457
KAREN KARPENTER 123458
[1] 更一般地說,只要您可以制定一個明確標識欄位名稱的正則運算式,就可以使用這種方法。
uj5u.com熱心網友回復:
使用這個可重用的函式:(
另見:#16257String >>>Regex>>> PSCustomObject)
function ConvertFrom-Text {
[CmdletBinding()]Param (
[Regex]$Pattern,
[Parameter(Mandatory = $True, ValueFromPipeLine = $True)]$InputObject
)
process {
if ($_ -match $pattern) {
$matches.Remove(0)
[PSCustomObject]$matches
}
}
}
$log = @(
'FIRST:BOB LAST:SMITH DOOR:MAIN ENTRANCE ID:123456 TIME:Friday, December 31, 2021 11:55:47 PM INCIDENT:19002304'
'FIRST:JOHN LAST:DOE DOOR:MAIN ENTRANCE ID:789101 TIME:Friday, December 31, 2021 11:55:47 PM INCIDENT:19002304'
)
$Log |ConvertFrom-Text -Pattern '\bFIRST:(?<First>\S*).*\bLAST:(?<Last>\S*).*\bID:(?<ID>\d )'
ID Last First
-- ---- -----
123456 SMITH BOB
789101 DOE JOHN
uj5u.com熱心網友回復:
假設日志檔案看起來就像我們在參考的文本中看到的那樣,你可以像這樣匹配它:
$log = @'
FIRST:BOB LAST:SMITH DOOR:MAIN ENTRANCE ID:123456 TIME:Friday, December 31, 2021 11:55:47 PM INCIDENT:19002304
FIRST:JOHN LAST:DOE DOOR:MAIN ENTRANCE ID:789101 TIME:Friday, December 31, 2021 11:55:47 PM INCIDENT:19002304
'@
$re = [regex]'(?si)FIRST:(?<first>.*?)\s*LAST:(?<last>.*?)\s*DOOR.*?ID:(?<id>\d )'
foreach($match in $re.Matches($log))
{
'{0} {1} {2}' -f
$match.Groups['first'].Value,
$match.Groups['last'].Value,
$match.Groups['id'].Value
}
# Results in:
BOB SMITH 123456
JOHN DOE 789101
此正則運算式應該適用于多行字串,因此您可以使用-Rawfor Get-Content:
$re = [regex]'(?si)FIRST:(?<first>.*?)\s*LAST:(?<last>.*?)\s*DOOR.*?ID:(?<id>\d )'
$result = foreach($match in $re.Matches((Get-Content ./test.log -Raw)))
{
[pscustomobject]@{
First = $match.Groups['first'].Value
Last = $match.Groups['last'].Value
ID = $match.Groups['id'].Value
}
}
$result | Export-Csv path/to/newlog.csv -NoTypeInformation
見https://regex101.com/r/WluWpD/1的正則運算式的解釋。
轉載請註明出處,本文鏈接:https://www.uj5u.com/ruanti/401849.html
