3

I am trying to find an elegant way of transforming data below into collection of Powershell objects but unfortunately I am unable to find a simple way of doing it. Would someone be able to help me here?

Name: ENC1
IPv4 Address: 172.16.2.101
Link Settings: Forced, 100 Mbit, Full Duplex
Name: ENC2
IPv4 Address: 172.16.2.103
Link Settings: Forced, 100 Mbit, Full Duplex
Name: ENC3
IPv4 Address: 172.16.2.103
Link Settings: Forced, 100 Mbps, Full Duplex
Name: ENC4
IPv4 Address: 172.16.2.104
Link Settings: Forced, 100 Mbps, Full Duplex

This is what I came up with.

$out = @()
$text = Get-Content input.txt
$count = 0
do {
$line = ($text | select -Skip $count -first 3)
$obj = "" | Select Name,IP,Settings
$obj.Name = $line[0].split(":")[1]
$obj.IP = $line[1].split(":")[1]
$obj.Settings = $line[2].split(":")[1]
$out += $obj
$count = $count+3
} until ($count -eq $text.count)
$out

Is there simplier way of doing it?

2
  • That data has probably been transformed from something else - is there any way you can get access to that and possibly skip the parsing altogether? Commented May 13, 2014 at 13:10
  • the data is generated as a part of the script output. I would have to parse it one way or another.However it this case this is not relevant - the question was for any data that was presented this way. Commented May 13, 2014 at 14:21

1 Answer 1

7

Using a Switch:

$data = (@'
Name: ENC1
 IPv4 Address: 172.16.2.101
 Link Settings: Forced, 100 Mbit, Full Duplex
 Name: ENC2
 IPv4 Address: 172.16.2.103
 Link Settings: Forced, 100 Mbit, Full Duplex
 Name: ENC3
 IPv4 Address: 172.16.2.103
 Link Settings: Forced, 100 Mbps, Full Duplex
 Name: ENC4
 IPv4 Address: 172.16.2.104
 Link Settings: Forced, 100 Mbps, Full Duplex
'@).split("`n") |
foreach {$_.trim()}

Switch -Regex ($data) 
{
 '^Name: (.+)' {$obj = [PSCustomObject]@{Name=$Matches[1];IP=$null;Settings=$null}}
 '^IPv4 Address: (.+)' {$obj.IP = $matches[1]}
 '^Link Settings: (.+)' {$obj.Settings = $Matches[1];$obj}
}



Name                                 IP                                   Settings                            
----                                 --                                   --------                            
ENC1                                 172.16.2.101                         Forced, 100 Mbit, Full Duplex       
ENC2                                 172.16.2.103                         Forced, 100 Mbit, Full Duplex       
ENC3                                 172.16.2.103                         Forced, 100 Mbps, Full Duplex       
ENC4                                 172.16.2.104                         Forced, 100 Mbps, Full Duplex       

Edit: after some consideration, I think I like this pattern better:

$DefValue = 'Parse error. Check input.'
Switch -Regex ($data) 
{
 '^Name: (.+)' {$obj;$obj = [PSCustomObject]@{Name=$Matches[1];IP=$DefValue;Settings=$DefValue}}
 '^IPv4 Address: (.+)' {$obj.IP = $matches[1]}
 '^Link Settings: (.+)' {$obj.Settings = $Matches[1]}
}
Sign up to request clarification or add additional context in comments.

6 Comments

i dont undertand the last line. Why do we have to append ";$obj" to make it works ?
@Kayasax - That puts the finished object onto the pipeline. Without that, it just gets destroyed when $obj gets created as a new object when it hits then next Name line.
+1 Cool solution. Learned something new today. I would have tried to split at Name: and done it the hard way :)
I was previously impressed by your Powershell multiline regex matching post that demonstrated a solution with, in a sense, only two lines of code (not counting the code to prepare the data). But this is yet another elegant solution!
Thanks! I added an alternate solution that does a better job (IMHO) of detecting possible missing entries in the input data.
|

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.