Parsing / formatting strings with powershell
This original question was not about powershell. I am assuming these base premises:
- We are running Windows 7
- We want to parse the result of systeminfo utility that comes with Windows 7
- We want to extract information about开发者_运维百科 network adapters from the output and put it into some data structure for further processing.
Now, I know that there are better ways of getting Network card information than running systeminfo and parsing the output. My interest is not in this particular utility. I'm considering a generic task of parsing / format some text in powershell. I feel that powershell is well suited for this kind of tasks, maybe better than C# (depending on particular requirements). This is why I offer my answer in powershell to the original question.
My question, though is this. I always feel that some of powershell syntax is a bit cumbersome. How would you improve my code? Note that the code does not have to return exactly the same results in exactly the same structure. I'm looking for tricks that can help with text parsing / processing. I've seen once and again community's ingenuity in approaching a lot of task. I've seen simple solutions to complex problems that are not at all obvious until someone shows you how. This is why I'm asking.
Here is the code:
$networkCards = systeminfo | ForEach-Object {$a=0} {
if ($_.startswith("Network Card(s)")) {$a=1} else {if ($a) {$_}}
}
$networkCards | ForEach-Object {$data=@{}} {
if ($_.trim().startswith("[")) {
$c = $_.trim(); $data[$c] = @()} else {$data[$c] += $_.trim()
}
}
#Now we have a hash table with the keys as requested in the question
#and the values are lists of separate strings, but those can be easily
#concatenated if needed. Let's display it:
$data
First of all, please stop using Powershell as usual script language.
PowerShell use object and parsing string is definitively NOT the good way to do what you want. I have to adapt your script to my language to get something in $data
And for me the things here under do not have mush sense but you construct a hashtable of array and I give you the way to exploit it.
So to use the $data you can write :
foreach ($key in $data.keys)
{
write-Host ("The name is {0}, the value is {1}" -f $key, $data[$key])
}
In my case it gives :
The name is [02]: fe80::391a:2817:8f3e:6f2f, the value is System.Object[]
The name is [02]: Intel(R) WiFi Link 5300 AGN, the value is System.Object[]
The name is [02]: fe80::c70:cc38:cf64:eb27, the value is System.Object[]
The name is [01]: 192.168.183.1, the value is System.Object[]
The name is [01]: 192.168.0.3, the value is System.Object[]
The name is [03]: VMware Virtual Ethernet Adapter for VMnet1, the value is System.Object[]
The name is [05]: Microsoft Virtual WiFi Miniport Adapter, the value is System.Object[]
The name is [02]: fe80::5d48:c4a:5987:ee73, the value is System.Object[]
The name is [04]: VMware Virtual Ethernet Adapter for VMnet8, the value is System.Object[]
The name is [01]: 192.168.234.1, the value is System.Object[]
The name is [01]: Intel(R) 82567LM Gigabit Network Connection, the value is System.Object[]
Because $data[$key] is an array. you can write :
foreach ($key in $data.keys)
{
write-Host ("The name is {0}" -f $key)
foreach($line in $data[$key])
{
Write-Host ("`t$line")
}
}
For me it gives :
The name is [02]: fe80::391a:2817:8f3e:6f2f
The name is [02]: Intel(R) WiFi Link 5300 AGN
Nom de la connexion : Connexion réseau sans fil
État : Support déconnecté
The name is [02]: fe80::c70:cc38:cf64:eb27
The name is [01]: 192.168.183.1
The name is [01]: 192.168.0.3
The name is [03]: VMware Virtual Ethernet Adapter for VMnet1
Nom de la connexion : VMware Network Adapter VMnet1
DHCP activé : Non
Adresse(s) IP
The name is [05]: Microsoft Virtual WiFi Miniport Adapter
Nom de la connexion : Connexion réseau sans fil 2
État : Support déconnecté
The name is [02]: fe80::5d48:c4a:5987:ee73
The name is [04]: VMware Virtual Ethernet Adapter for VMnet8
Nom de la connexion : VMware Network Adapter VMnet8
DHCP activé : Non
Adresse(s) IP
The name is [01]: 192.168.234.1
The name is [01]: Intel(R) 82567LM Gigabit Network Connection
Nom de la connexion : Connexion au réseau local
DHCP activé : Oui
Serveur DHCP : 192.168.0.254
Adresse(s) IP
I'll have a try at moderating the answer above :-) :
Although Powershell can be used to parse information from e.g. systeminfo, there are much better interfaces for information. Have a look at Get-WmiObject
. In this case, Get-WmiObject Win32_NetworkAdapter
or Win32_NetworkAdapterConfiguration
seems to come in mind. There are also Win32_NetworkProtocol
and Win32_NetworkConnection
that may give you the information you need.
Combine with Select-Object
, Sort-Object
and Format-Table
to present the data you need.
Everyone talking about objects is correct. The idea is to emit an object from one method directly into another, then act on that object. I'm no guru on PS, but I'm beginning to get the idea. Hopefully, this script will move you forward a little bit.
$text = @"
key1:value1
key2:value2
key3:value3
"@
$map = @{}
($text -split "`n") | Where-Object {$_ -imatch 'key2'} | foreach-object {$tokens = $_ -split ":"; $map.Add($tokens[0],$tokens[1])}
$map
精彩评论