[英]Retain carriage returns in text filtered through a regular expression
我需要搜索日志文件夾,並檢索最新日志。 然后,我需要過濾每個日志,提取相關信息並保存到另一個文件。
問題是我用來過濾日志的正則表達式刪除了回車符和換行符,因此新文件只包含一堆文本。
$Reg = "(?ms)\*{6}\sBEGIN(.|\n){98}13.06.2015(.|\n){104}00000003.*(?!\*\*)+"
get-childitem "logfolder" -filter *.log |
where-object {$_.LastAccessTime -gt [datetime]$Test.StartTime} |
foreach {
$a=get-content $_;
[regex]::matches($a,$reg) | foreach {$_.groups[0].value > "MyOutFile"}
}
日志結構:
******* BEGIN MESSAGE *******
<Info line 1>
Date 18.03.2010 15:07:37 18.03.2010
<Info line 2>
File Number: 00000003
<Info line 3>
*Variable number of lines*
******* END MESSAGE *******
基本上捕獲日期和文件編號為某個值的BEGIN
和END
之間的所有內容。 有誰知道我該怎么做而不丟失換行符? 我也嘗試使用Out-File | Select-String -Pattern $reg
Out-File | Select-String -Pattern $reg
,但是我在多行記錄上使用Select-String
從未成功。
想看看我是否可以使該正則表達式更好,但是現在,如果您正在使用那些正則表達式模式,則應該將文本文件作為單個字符串讀取,這會很有幫助。
$a=get-content $_ -Raw
或者如果您沒有PowerShell 3.0
$a=(get-content $_) -join "`r`n"
正如@Matt指出的,如果要進行多行匹配,則需要將整個文件讀取為單個字符串。 否則,您的(多行)正則表達式將一個接一個地應用於單行。 有幾種方法可以將文件內容作為單個字符串獲取:
(Get-Content 'C:\\path\\to\\file.txt') -join "`r`n"
Get-Content 'C:\\path\\to\\file.txt' | Out-String
Get-Content 'C:\\path\\to\\file.txt' -Raw
(需要PowerShell v3或更高版本) [IO.File]::ReadAllText('C:\\path\\to\\file.txt')
另外,我會稍微修改正則表達式。 大多數時候,日志消息的長度可能會有所不同,因此,如果日志消息發生更改,則匹配固定長度可能會失敗。 最好在字符串的不變部分上進行匹配,然后將其余部分保留為可變長度匹配。 而且我個人覺得分幾步進行這種內容提取要容易得多(使正則表達式更簡單)。 在您的情況下,我首先將日志條目彼此分開,然后過濾內容:
$date = [regex]::Escape('13.06.2015')
$fnum = '00000003'
$re1 = "(?ms)\*{7} BEGIN MESSAGE \*{7}\s*([\s\S]*?)\*{7} END MESSAGE \*{7}"
$re2 = "(?ms)[\s\S]*?Date\s+$date[\s\S]*?File Number:\s+$fnum[\s\S]*"
Get-ChildItem 'C:\log\folder' -Filter '*.log' | ? {
$_.LastAccessTime -gt [DateTime]$Test.StartTime
} | % {
Get-Content $_.FullName -Raw |
Select-String -Pattern $re1 -AllMatches |
select -Expand Matches |
% {
$_.Groups[1].Value |
Select-String -Pattern $re2 |
select -Expand Matches |
select -Expand Groups |
select -Expand Value
}
} | Set-Content 'C:\path\to\output.txt'
順便說一句,不要在循環內使用重定向運算符( >
)。 它將在每次迭代時覆蓋輸出文件的內容。 如果必須在循環內寫入文件,請使用附加重定向運算符( >>
)。 但是,從性能角度考慮,通常最好在流水線的末尾寫入輸出文件(請參見上文)。
我必須解決在完全不同的環境中換行符消失的問題。 當獲取文本文件的內容時,您得到的是一組記錄數組,其中每條記錄都是一行文本。
我發現在進行一些轉換后重新插入換行符的唯一方法是使用自動變量$ OFS(輸出字段分隔符)。 默認值為空格,但是如果將其設置為回車換行符,則會在單獨的行上獲得單獨的記錄。
因此,請嘗試以下操作(可能可行):
$OFS = "`r`n"
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.