A more or less direct equivalent of grep -A
does not exist in findstr
(or find
), Windows' native grep
equivalent. However, Select-String
in PowerShell has this with the -Context
parameter.
If I understand your script correctly, it means:
- Write an empty line
- Write all lines containing "Device_name", followed by four lines of context, followed by an empty line
- Write all lines containing "Device_Oops", followed by 45 lines of context, followed by an empty line
- Write all lines containing "Radar" if they either contain "Processes:" too or are within the first 150 lines following a line containing "Processes:"
- Write all lines containing three pairs of digits, separated by a colon that also contain either "error" or "restart", case-insensitively.
So it more or less comes down to something like:
$f = Get-Content $args[0]
function Emulate-Grep {
begin { $first = $true }
process {
if (!$first) { '--' }
$_.Line
$_.Context.PostContext
$first = false
}
}
Write-Host
$f | Select-String -CaseSensitive -Context 0,4 'Device_name' | Emulate-Grep; Write-Host
$f | Select-String -CaseSensitive -Context 0,45 'Device_Oops' | Emulate-Grep; Write-Host
[string[]]($f | Select-String -CaseSensitive -Context 0,150 'Processes:' | Emulate-Grep) -split "`n" -cmatch 'Radar'; Write-Host
$f -match 'd{2}(:d{2}){2}' -match 'error|restart'
(Untested)
Note that this is slightly ugly due to the attempt to emulate grep
's output behaviour.
If you just need matching lines and the following, then I'd simply write a small function:
function Get-Matching([array]$InputObject, [string]$Pattern, [int]$Context = 0) {
$n = $InputObject.Length - 1
0..$n |
where { $InputObject[$_] -cmatch $Pattern } |
foreach { $InputObject[$_..($_+$Context)] }
}
And then use it in a script that isn't so complex anymore (still trying to recreate some of your output choices, e.g. empty lines):
$f = gc $args[0]
Write-Host
Get-Matching $f Device_name 4; Write-Host
Get-Matching $f Device_Oops 45; Write-Host
Get-Matching $f 'Processes:' 150 | ? { $_ -cmatch 'Radar' }; Write-Host
Get-Matching $f 'd{2}(:d{2}){2}' | ? { $_ -match 'error|restart' }
You'll also notice that I got rid of Select-String
, a cmdlet I never really understood the purpose of (except providing a close match of grep
/findstr
, but usually I find other means more flexible).
与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…