4

So I have a array that I need to search through line by line and divide up by interfaces. My code loops through this file line by line. I want to split up the interfaces by the "!" character and add the the strings to an element in an array so I can do further parsing.

Here's what the content of the file looks like.

!
interface Loopback0
 description MANAGEMENT
 ip address 172.xxx.xxx.x
!
interface FastEthernet0/0
 description m<1> A<LAN on chr-city>
 no ip address
 ip flow ingress
 duplex auto
 speed auto
!
interface FastEthernet0/0.50
 description Management
 encapsulation dot1Q 50 native
 ip address 172.xxx.xxx.x
!
interface FastEthernet0/0.51
 description Transit
 encapsulation dot1Q 51
 ip address 172.xxx.xxx.x
 service-policy input mark
!
interface FastEthernet0/1
 no ip address
 shutdown
 duplex auto
 speed auto
!
interface Serial0/0/0
 description m<1> WAN<> V<CL> 
 bandwidth 1536
 ip address 172.xxx.xxx.x
 ip flow ingress
 no ip mroute-cache
 service-module t1 timeslots 1-24
 no cdp enable
 service-policy output shape
!
router bgp 65052

search the config archive file code

for ($m=0; $m -lt $configFileContents.length; $m++) {
     $index = 0
         if($configFileContents[$m] -eq "interface Loopback0"){ #starting spot
                $a = @()
                While($configFileContents[$m] -notmatch "router bgp") { #ending spot              
                       if($configFileContents[$m] -ne "!") { #divide the elements
                            $a[$index] += $configFileContents[$m] 
                         $m++
                        } else {
                                $index++
                                $m++
                           }
                 }

                Write-Host "interface archive section" -BackgroundColor Green
               $a
                Write-Host "end of interface archive section"  
         }`

Question: How do I add all the interface strings between the "!" to one element in my array and all the next ones to the second element and so on?

Updated Code

        $raw = [IO.File]::ReadAllText("$recentConfigFile")
        $myArr = @()
        $raw.Split("!") | % {$myArr += ,$_.Split("`n")}


        $i = 0
        $myArr | % {
            if ($_[0].Trim() -eq "interface Loopback0") {
                $start = $i
                } elseif ($_[0].Trim() -eq "router bgp 65052") {
                $end = $i
                }
            $i++
            }

        $myArr | Select-Object -Skip $start -First ($end-$start)
runcmd
  • 255
  • 2
  • 4
  • 11
  • 2
    How are you getting the initial array? If you're reading a text file using `Get-ChildItem` or the like you're really making this much too hard on yourself. – Tim Ferrill Jun 23 '14 at 17:49

2 Answers2

1

You are working too hard with the loops and conditions. This should get you an array with each interface element as a sub-array:

$raw = [IO.File]::ReadAllText("C:\Users\Public\Documents\Test\Config.txt")
$myArr = @()
$raw.Split("!") | % {$myArr += ,$_.Split("`n")}

If all you want is each interface section as a string element you can change the last two lines to this:

$myArr = $raw.Split("!")

There may be a little cleanup to do with the array after that, but this should get you 99% of the way there. For example, to get only the elements between interface Loopback0 and router bgp 65052:

$i = 0
$myArr | % {
    if ($_[0] -like "*interface Loopback0*") {
        $start = $i
        } elseif ($_[0] -like "*router bgp 65052*") {
        $end = $i
        }
    $i++
    }

$myArr | Select-Object -Skip $start -First ($end-$start)
Tim Ferrill
  • 418
  • 4
  • 8
  • This works wonderfully my only problem is that theres other information in the file as well.. and the above information was the only stuff i wanted to grab and parse out. Thats why i put it in an array and made a starting and stopping point – runcmd Jun 23 '14 at 17:55
  • Added some bits to filter out before and after the strings you requested. – Tim Ferrill Jun 23 '14 at 18:09
  • Okay I get this error. `Select-Object : Cannot validate argument on parameter 'Skip'. The argument is null, empty, or an element of the argument collection contains a null value. Supply a collection that does not contain any null values and then try the command again. At C:\Users\kroumat\Desktop\Powershell\Scripts\parse.ps1:124 char:42 + $myArr | Select-Object -Skip $start -First ($end-$start)` I'm going to update the question with the code for you to see as well. – runcmd Jun 23 '14 at 18:29
  • That means it's not matching on the first string. Your best bet is probably to change the comparison operator from `-eq` to `-like` and add wildcards. I'll update the answer. – Tim Ferrill Jun 23 '14 at 18:35
  • Same error as before – runcmd Jun 23 '14 at 18:53
  • Still on the `-Skip` parameter? Or is it on `-First` now? Both strings match the start and end lines you're after correct? And you changed both the if and elseif conditions to use `-like` and the strings with wildcards? – Tim Ferrill Jun 23 '14 at 18:58
  • Yep still on the skip and I made every change – runcmd Jun 23 '14 at 19:07
  • Then it's still not matching the string. I'd take a look at the config file and try and determine why it's not matching. Is there an extra space between the words or something? You could try putting a wildcard `*` between the words as in `"*interface*Loopback0*"`. – Tim Ferrill Jun 23 '14 at 19:11
  • You have some scoping issues. You declare your `$start` and `$end` variables inside curly braces so when you go to retrieve them when you run `select-object`, they're gone. For a test, just replace them with hard coded numbers and you'll see that it works. To resolve, just declare `$start` and `$end` at the same time you declare your incrementer, `$i`. – pk. Jun 23 '14 at 22:15
  • It's not a scoping issue. Curly braces don't change the scope unless they're indicating a function/cmdlet. It's working flawlessly for me. – Tim Ferrill Jun 23 '14 at 22:19
0

First split in blocks

$x = Get-Content -Path 'D:\powershell\Files\input.txt' 
$x2 = $x -join "`r`n"
$x3 = $x2 -split "!`r`n"

in short:

$x = @( $(@( Get-Content -Path 'D:\powershell\Files\input.txt'  ) -join "`r`n" ) -split "!`r`n" )

Then output colorized

ForEach ($line in $x) {
    $local:lineArr = @( $line -split "`r`n" )
    $local:arrayInterfaces = @(  $local:lineArr | Where-Object {$_ -match '\s*interface\s'} )
    $local:arrayNonInterfaces = @( $local:lineArr | Where-Object { $local:arrayInterfaces -notcontains $_ } )

    Write-Host -ForegroundColor Red $( $local:arrayInterfaces -join "`r`n" )
    Write-Host -ForegroundColor Green $( $local:arrayNonInterfaces -join "`r`n" )
    Write-Host ( '#' * 60 )
}
filimonic
  • 323
  • 3
  • 13