PowerShell query: how to process a file
I often开发者_Go百科 want to process a file resulting in a modified output file. I can't seem to find the PowerShell way to do this - it always ends up looking like code in a one-liner, IYSWIM. This is an example.
I have an LMHOSTS file. Don't ask why! I want to get a new LMHOSTS file that only contains servers that respond to pings. I also want to pass through any comment lines.
Comment lines begin with a #.
Data lines are something like this (space-separated):
10.123.177.1 SVRDS1 #PRE #DOM:DOM1
or this:
10.241.177.30 SVRDS30 #PRE
This is what I've got (with thanks to Luke for help with Ping-Host):
gc 'C:\work\lmhosts.txt' | % { if ($_ -like '#*') { $_ | out-file 'C:\work\lmhosts2.txt' -append } else { if ($(Ping-Host $_.Substring(0, $_.indexof(' ')) -count 1 -timeout 10).received -eq 1) { $_ | out-file 'C:\work\lmhosts2.txt' -append } } }
It works but it's not nice. I've taken a programmer's approach but done it as a one-liner. Is there a better way of doing it, that's more 'shell' and less 'code'?
In this particular example, you are filtering the contents of 1 file and outputting it to another. Where-Object is usually a good choice for this. You can then simplify your one-liner a bit:
gc 'C:\work\lmhosts.txt' |
?{ ($_ -like '#*') -or
($(Ping-Host $_.Split(' ')[0]) -count 1 -timeout 10).received -eq 1) } >
'C:\work\lmhosts2.txt'
Some notes:
- "?" is an alias for Where-Object
- The -or operator will short circuit, that is, if the first operand results in True, the second will not bother executing.
- You can use the redirection operator ">" instead of "| Out-File".
- I replaced Substring with Split, it seemed slightly simpler, not sure if works in general with your input.
Whitespace is your friend! In Powershell scripts I write that aren't immediately thrown away, almost every '|' is followed by a newline + indent.
精彩评论