Welcome Forums General PowerShell Q&A Parsing Text Logic

Viewing 3 reply threads
  • Author
    Posts
    • #166783
      Participant
      Topics: 2
      Replies: 2
      Points: 15
      Rank: Member

      I’m hoping to get some help with a problem that has me stumped for the past few hours.  I’m trying to gather inventory information from a text string that looks like the following variable that is set to $SwitchInfo

      $SwitchInfo = 'Switch                      Type               Address          Model
      
      --------------------------- ------------------ ---------------- ---------------
      
      AMS01-FLEXE007-N2428-SW1(FOC2204M1KH) cluster-network 172.19.3.26 NX3132V
      
           Serial Number: Unknown
      
          Version Source: CDP
      
      AMS01-FLEXE007-N2428-SW2(FOC2204K1K7) cluster-network 172.19.3.27 NX3132V
      
           Serial Number: Unknown
      
          Version Source: CDP
      
      fcp-dst1p2s1(FDO22133NZM)   management-network 10.168.1.20      OTHER
      
           Serial Number: Unknown
      
          Version Source: CDP/ISDP
      
      fcp-dst1p2s2(FDO22133D8F)   management-network 10.168.1.21      OTHER
      
           Serial Number: Unknown
      
      vesw20-88732                cluster-network    10.33.99.168     CN1610
      
           Serial Number: 41014560299
      
          Version Source: ISDP
      
      vesw21-88732                cluster-network    10.33.99.169     CN1610
      
           Serial Number: 41011850242
      
          Version Source: ISDP'

      I need to gather Make, Model, Serial, and IP.  Since there is a difference between how Cisco and Brocade display their information, I’m not sure on the proper logic for this.  When I make it work for one, the other doesn’t work.  Any help with this is greatly appreciated.  Here’s what I have so far.

      Sorry for formatting, can’t figure out how to get indents and color into code.

      Foreach($line in $SwitchInfo){
      If($line -like "*cluster-network*"){
      $SwitchName = ($($line -split "\s+")[0]).Split("(")[0]
      $SwitchIP = ($line -split "\s+")[2]
      $SwitchModel = ($line -split "\s+")[3]
      Switch ($SwitchModel) {
      'CN1610' {$SwitchMake = 'Brocade'}
      'NX3132V' {$SwitchMake = 'Cisco'}
      }
      #Temporarily Commented out Cisco Serial gathering to make Brocade side work
      #if($SwitchMake -eq 'Cisco') {
      #$SwitchSerial = ((($line -split "\s+")[0]).Split("(")[1]).split(")")[0]
      #}
      }
      elseif($line -like "*Serial Number:*"){ # -and $SwitchMake -eq 'Brocade'){ 
      $SwitchSerial = ($line -split "\s+")[3] 
      $Inventory += New-Object psobject -Property @{ 
      Count = 1
      ContractID = 'N/A'
      Status = 'Production'
      Name = $SwitchName;
      Function = 'Switch-CL'
      Make = $SwitchMake
      Model = $SwitchModel;
      Serial = $SwitchSerial;
      SiteID = $SiteCode
      LocationCode = $ClusterData.ClusterLocation
      ClusterMGMT_IP = $ClusterData.NcController.Address.IPAddressToString
      NodeMGMT_IP = $SwitchIP;
      NodeILO_IP = ''
      Environment = ''
      Purchaser = 'Flexential'
      Install_Date = Get-Date -format "MM/dd/yyyy"
      Vendor_EndDate = ''
      Notes = 'Auto Generated via Get-NTAPInventory' 
      }
      }
      }
    • #166915
      Participant
      Topics: 1
      Replies: 20
      Points: 77
      Helping Hand
      Rank: Member

      I find it easier to break up the information into records using a regular expression rather than examining line by line.  Then you can just extract the information you need from each record.  I hope this code sets you on the right path.

      https://gist.github.com/DrBob5188/841acef65713ba66e9d4a09b4405a1ce

      • #166987
        Participant
        Topics: 2
        Replies: 2
        Points: 15
        Rank: Member

        Thank you very much, this method does appear to be much cleaner than how I was going about it.  That said, I’m still getting my bearings on Regex and don’t fully understand the format.

        Can you explain what the following expressions mean:

        (?m)(?=^.+-network)

        Also, I understand the following grabs everything between parenthesis, but any chance you can break down what it’s doing?

        \(([^)]+)\)

        Thanks again for your assistance with this, I have spent entirely way too much time trying to figure it out with “if” statements.

    • #166957
      Participant
      Topics: 2
      Replies: 2
      Points: 15
      Rank: Member

      Thank you very much, this method does appear to be much cleaner than how I was going about it.  That said, I’m still getting my bearings on Regex and don’t fully understand the format.

      Can you explain what the following expressions mean:

      (?m)(?=^.+-network)

      Also, I understand the following grabs everything between parenthesis, but any chance you can break down what it’s doing?

      \(([^)]+)\)

      Thanks again for your assistance with this, I have spent entirely way too much time trying to figure it out with “if” statements.

       

    • #166978
      Participant
      Topics: 2
      Replies: 512
      Points: 1,309
      Helping Hand
      Rank: Community Hero

      First one broken down:

      '(?m)(?=^.+-network)'
      
      (?m)     -- multi-line match mode. Don't think this is actually typically *needed* in PS, but it doesn't hurt to be explicit.
      (?=      -- Zero-length lookahead match (basically it means "match right before this thing specified between '(?=' and the closing parenthesis)
      ^        -- start of the string
      .+       -- period represents "any character", plus sign indicates one or more of the previous token; thus, "one or more of anything"
      -network -- all literal characters here, just match this text.

      Reference for multiline mode for you to read up on: https://www.w3schools.com/jsref/jsref_regexp_m.asp 🙂

      As for the second one:

      '\(([^)]+)\)'
      
      \(    -- escaped (literal) opening parenthesis
      (     -- start capture group
      [^)]+ -- match one or more characters that aren't a closing parenthesis
      )     -- end capture group
      \)    -- literal (escaped) closing parenthesis

       

      • #167029
        Participant
        Topics: 1
        Replies: 20
        Points: 77
        Helping Hand
        Rank: Member

        Thanks Joel, your explanation is pretty much spot on.

        The (?m) multiline option is required if you are trying to split a string with embedded newline characters (\r or \n).

        The .+ in the lookahead expression matches anything except an end of line (ie \r \n).  Using it is kind of sloppy because the regular expression engine will match anything up to the end of the line before it has to start backtracking one character at a time until it finds the -network.  Backtracking is inefficient. However, as the lines are unlikely to be too long, the backtracking is minimal and constrained by the first appearance of a newline. Even with a lot of records that shouldn’t hurt performance too much.

        As an alternative to regular expressions you might also try the ConvertFrom-String cmdlet.  That allows you to take a template based approach to data extraction.  I haven’t had much success with it, but to be honest I didn’t persevere for very long either.  The learning curve for the cmdlet is probably easier than regular expressions.

         

Viewing 3 reply threads
  • The topic ‘Parsing Text Logic’ is closed to new replies.