使用 Select-String 从 txt 文件中提取括号中的所有事件标题
Using Select-String to extract all event titles, which are in parentheses, from a txt file
我试图在我的一个日志中提取事件的标题,它只是一个包含大量数据的文本文件。文件名是 eventlog-1-5-2016.txt
(日期始终是当前日期)。文件中的每一行都是一个这样的事件:
1-1-16(Commodore Rally)Address|Time
1-2-16(Open House)Address|Time
我只想遍历文件并提取括号中的标题,不包括括号本身,并将列表输出到控制台或文本文件。
我也试过输出到 txt 文件,但我遗漏了一些东西。你能告诉我为什么这不起作用吗:
控制台:
Select-String -Path c:\log\eventlog-1-5-2016.txt -Pattern '\(([^\)]+)\)' -AllMatches |
% { $_.Matches }
到文件:
Select-string -Path c:\log\eventlog-1-5-2016.txt -Pattern '\(([^\)]+)\)' -AllMatches |
% { $_.Matches } | { $_.Value > C:\log\results.txt
如果错误,甚至是更好的方法。
奖金问题,路径可以自动计算当前日期并更正文件名以便于将来粘贴吗? (不是专业!)
发生的事情是 Select-String
并不像您认为的那样。它将匹配模式,但不是 return 匹配的部分,而是 return 整个匹配字符串。因此,语句 return 为您提供了整个匹配行,而不仅仅是括号中的子字符串。这是常见的 cause for confusion.
作为 link rot 情况下的一个简单示例,
[regex]$rx = '\(([^\)]+)\)'
cat C:\Temp\logfile.txt | % { $rx.Matches( $_ ).value }
(Commodore Rally)
(Open House)
当前日期可以这样确定:
(Get-Date).ToString('d-M-yyyy')
此外,您的正则表达式可以通过使用 non-greedy 匹配来稍微简化:
`\((.+?)\)
如果您只需要括号之间的文本,您需要捕获组的值而不是完整匹配:
$date = (Get-Date).ToString('d-M-yyyy')
Select-String -Path "C:\log\eventlog-$date.txt" -Pattern '\((.+?)\)' -AllMatches |
ForEach-Object { $_.Matches } |
ForEach-Object { $_.Groups[1] } |
ForEach-Object { $_.Value } |
Out-File 'C:\log\results.txt'
如果您有 PowerShell v3 或更新版本,您可以折叠 ForEach-Object
语句:
Select-String -Path "C:\log\eventlog-$date.txt" -Pattern '\((.+?)\)' -AllMatches |
ForEach-Object { $_.Matches.Groups[1].Value } |
Out-File 'C:\log\results.txt'
或者您可以使用 -match
运算符:
Get-Content "C:\log\eventlog-$date.txt" |
Where-Object { $_ -match '\((.+?)\)' } |
ForEach-Object { $matches[1] } |
Set-Content 'C:\log\results.txt'
我试图在我的一个日志中提取事件的标题,它只是一个包含大量数据的文本文件。文件名是 eventlog-1-5-2016.txt
(日期始终是当前日期)。文件中的每一行都是一个这样的事件:
1-1-16(Commodore Rally)Address|Time 1-2-16(Open House)Address|Time
我只想遍历文件并提取括号中的标题,不包括括号本身,并将列表输出到控制台或文本文件。
我也试过输出到 txt 文件,但我遗漏了一些东西。你能告诉我为什么这不起作用吗:
控制台:
Select-String -Path c:\log\eventlog-1-5-2016.txt -Pattern '\(([^\)]+)\)' -AllMatches |
% { $_.Matches }
到文件:
Select-string -Path c:\log\eventlog-1-5-2016.txt -Pattern '\(([^\)]+)\)' -AllMatches |
% { $_.Matches } | { $_.Value > C:\log\results.txt
如果错误,甚至是更好的方法。
奖金问题,路径可以自动计算当前日期并更正文件名以便于将来粘贴吗? (不是专业!)
发生的事情是 Select-String
并不像您认为的那样。它将匹配模式,但不是 return 匹配的部分,而是 return 整个匹配字符串。因此,语句 return 为您提供了整个匹配行,而不仅仅是括号中的子字符串。这是常见的 cause for confusion.
作为 link rot 情况下的一个简单示例,
[regex]$rx = '\(([^\)]+)\)'
cat C:\Temp\logfile.txt | % { $rx.Matches( $_ ).value }
(Commodore Rally)
(Open House)
当前日期可以这样确定:
(Get-Date).ToString('d-M-yyyy')
此外,您的正则表达式可以通过使用 non-greedy 匹配来稍微简化:
`\((.+?)\)
如果您只需要括号之间的文本,您需要捕获组的值而不是完整匹配:
$date = (Get-Date).ToString('d-M-yyyy')
Select-String -Path "C:\log\eventlog-$date.txt" -Pattern '\((.+?)\)' -AllMatches |
ForEach-Object { $_.Matches } |
ForEach-Object { $_.Groups[1] } |
ForEach-Object { $_.Value } |
Out-File 'C:\log\results.txt'
如果您有 PowerShell v3 或更新版本,您可以折叠 ForEach-Object
语句:
Select-String -Path "C:\log\eventlog-$date.txt" -Pattern '\((.+?)\)' -AllMatches |
ForEach-Object { $_.Matches.Groups[1].Value } |
Out-File 'C:\log\results.txt'
或者您可以使用 -match
运算符:
Get-Content "C:\log\eventlog-$date.txt" |
Where-Object { $_ -match '\((.+?)\)' } |
ForEach-Object { $matches[1] } |
Set-Content 'C:\log\results.txt'