RegEx Pattern Suggestions...

Hello RegEx-ers. I am trying to parse through the following data looking match the following. I can get a hack to make it work, but I am sure there can be a much better way :slight_smile:

Data that Im trying to parse:

2960S-1#sh license 
Index 1 Feature: lanlite        
        Period left: 0  minute  0  second  
Index 2 Feature: lanbase        
        Period left: Life time
        License Type: Permanent
        License State: Active, In Use
        License Priority: Medium
        License Count: Non-Counted

Current Reg Ex Match Pattern that semi works. I had to use an OR BUT I want this to be AND not OR however I just couldn’t make it work with AND.
Very UGLY :slight_smile:

Options Set True: Greedy, Allow Empty Matches, String Begin/End is line begin/end, Line End type any.
(?<=Index\\s\\d\\sFeature:\\s).+(?=\\s)|(?<=\\s\\s\\s\\s\\s\\s\\s\\s\\s\\s\\s\\s\\s\\s\\s\\s\\sPeriod\\sLeft:\\s).+(?=\\s)

Thank you for your help once again.
Mike

What do you want to extract from the data when you’re done? It looks like you want:

lanlite
0 minute 0 second
lanbase
Life time

Is that it?

Oh, I see what you’re trying to do. You want to capture both parts in the same pattern for each section. This will do it:

"(?mi-Us)Index \\d Feature: (.*)\
\\s*Period left: (.*)"

The feature will be in SubExpressionString(1) and the period in SubExpressionString(2). Trim each result to get rid of the trailing spaces.

Kem this is a bit closer but still ugly.

(Index\s\d)|(?<=Feature:\s).+(?=\s)|(?<=Period\sleft:\s).+(?=\s)|(?<=License\sType:\s).+(?=\s)|(?<=License\sState:\s).+(?=\s)|(?<=License\sPriority:\s).+(?=\s)|(?<=License\sCount:\s).+(?=\s)

[quote=57623:@Kem Tekinay]Oh, I see what you’re trying to do. You want to capture both parts in the same pattern for each section. This will do it:

"(?mi-Us)Index \\d Feature: (.*)\
\\s*Period left: (.*)"

The feature will be in SubExpressionString(1) and the period in SubExpressionString(2). Trim each result to get rid of the trailing spaces.[/quote]
Ooooh nice thanks Kem! Something new to try :slight_smile: Awesome and thanks!

No problem.

This pattern assumes you are only interested in those two items, and that the Period Left line will always follow the Index Feature line.

Thanks! I am trying it now. :slight_smile: I keep forgetting you can look inside of SubExpressionString like that.

Kem I can’t get it to match and I think it’s because I am storing the data in an array so it may be throwing off the pattern a bit. Do you mind spot checking my code? If I cut the match pattern in half (?mi-Us)Index \d Feature: (.*) it matches.

Thank you again so much.

  Dim License_RegEx as RegEx
  Dim License_RegExMatch as RegExMatch
  Dim Feature_HitText as String
  Dim PeriodLeft_HitText as String
  License_RegEx = New RegEx
  License_RegEx.Options.CaseSensitive = False
  License_RegEx.Options.Greedy = True
  License_RegEx.Options.MatchEmpty = True
  License_RegEx.Options.DotMatchAll = False
  License_RegEx.Options.StringBeginIsLineBegin = True
  License_RegEx.Options.StringEndIsLineEnd = True
  License_RegEx.Options.TreatTargetAsOneLine = False
  License_RegEx.SearchPattern = "(?mi-Us)Index \\d Feature: (.*)\
\\s*Period left: (.*)"
  
  for i as integer = 0 to UBound(Cisco_ShowLicenseArrayResults)
    License_RegExMatch = License_RegEx.Search(Cisco_ShowLicenseArrayResults(i))
    while License_RegExMatch <> nil
      if License_RegExMatch.SubExpressionString(1) <> "" Then
        Feature_HitText = License_RegExMatch.SubExpressionString(1)
      end if
      if License_RegExMatch.SubExpressionString(2) <> "" Then
        PeriodLeft_HitText = License_RegExMatch.SubExpressionString(2)
      end if
      License_RegExMatch = License_RegEx.Search
    Wend
  Next i

I tried flattening the Array into a flat string with no luck matching.

  Dim License_RegEx as RegEx
  Dim License_RegExMatch as RegExMatch
  Dim Feature_HitText as String
  Dim PeriodLeft_HitText as String
  License_RegEx = New RegEx
  License_RegEx.Options.CaseSensitive = False
  License_RegEx.Options.Greedy = True
  License_RegEx.Options.MatchEmpty = True
  License_RegEx.Options.DotMatchAll = False
  License_RegEx.Options.StringBeginIsLineBegin = True
  License_RegEx.Options.StringEndIsLineEnd = True
  License_RegEx.Options.TreatTargetAsOneLine = False
  License_RegEx.SearchPattern = "(?mi-Us)Index \\d Feature: (.*)\
\\s*Period left: (.*)"
  
// Flatten Out Array for Testing
  Dim FormattedString as String 
  for i as integer = 0 to UBound(Cisco_ShowLicenseArrayResults)
    FormattedString = FormattedString + Cisco_ShowLicenseArrayResults(i)
  Next i
  
  License_RegExMatch = License_RegEx.Search(FormattedString)
  while License_RegExMatch <> nil
    if License_RegExMatch.SubExpressionString(1) <> "" Then
      Feature_HitText = License_RegExMatch.SubExpressionString(1)
    end if
    if License_RegExMatch.SubExpressionString(2) <> "" Then
      PeriodLeft_HitText = License_RegExMatch.SubExpressionString(2)
    end if
    License_RegExMatch = License_RegEx.Search
  Wend

try
FormattedString = Cisco_ShowLicenseArrayResults.join(EndOfLine.UNIX)

It’s working here when I do the search on the text as a string. Looks like your flattening code doesn’t add linebreaks.

Thanks Jim! Ill try that.

Something is weird here. I can copy the results I get from the Formatted string into RegExRx and it matches fine, but it never matches in Xojo. Am I missing something? I am using 2013R4.1

  Dim License_RegEx as RegEx
  Dim License_RegExMatch as RegExMatch
  Dim Feature_HitText as String
  Dim PeriodLeft_HitText as String
  License_RegEx = New RegEx
  License_RegEx.Options.CaseSensitive = False
  License_RegEx.Options.Greedy = True
  License_RegEx.Options.MatchEmpty = True
  License_RegEx.Options.DotMatchAll = False
  License_RegEx.Options.StringBeginIsLineBegin = True
  License_RegEx.Options.StringEndIsLineEnd = True
  License_RegEx.Options.TreatTargetAsOneLine = False
  License_RegEx.SearchPattern = "(?mi-Us)Index \\d Feature: (.*)\
\\s*Period left: (.*)"
  
  // Flatten Out Array for Testing
  Dim FormattedString as String = Join(Cisco_ShowLicenseArrayResults,EndOfLine.UNIX)
  
  License_RegExMatch = License_RegEx.Search(FormattedString)
  while License_RegExMatch <> nil
    if License_RegExMatch.SubExpressionString(1) <> "" Then
      Feature_HitText = License_RegExMatch.SubExpressionString(1)
    end if
    if License_RegExMatch.SubExpressionString(2) <> "" Then
      PeriodLeft_HitText = License_RegExMatch.SubExpressionString(2)
    end if
    License_RegExMatch = License_RegEx.Search
  Wend

It works here with 2013r3.3/mac

Thanks Jim … Im Mac 2013r4.1… Ill try 3.3. Thanks!

This is my test code in 2014r1, and it works perfectly. I created the array by copying the text you gave us above and converting it to an array.


  Dim License_RegEx as RegEx
  Dim License_RegExMatch as RegExMatch
  Dim Feature_HitText as String
  Dim PeriodLeft_HitText as String
  License_RegEx = New RegEx
  License_RegEx.Options.CaseSensitive = False
  License_RegEx.Options.Greedy = True
  License_RegEx.Options.MatchEmpty = True
  License_RegEx.Options.DotMatchAll = False
  License_RegEx.Options.StringBeginIsLineBegin = True
  License_RegEx.Options.StringEndIsLineEnd = True
  License_RegEx.Options.TreatTargetAsOneLine = False
  License_RegEx.SearchPattern = "(?mi-Us)Index \\d Feature: (.*)\
\\s*Period left: (.*)"
  
  dim Cisco_ShowLicenseArrayResults() as string = Array( _
  "2960S-1#sh license ", _
  "Index 1 Feature: lanlite        ", _
  "        Period left: 0  minute  0  second  ", _
  "Index 2 Feature: lanbase        ", _
  "        Period left: Life time", _
  "        License Type: Permanent", _
  "        License State: Active, In Use", _
  "        License Priority: Medium", _
  "        License Count: Non-Counted" _
  )
  
  // Flatten Out Array for Testing
  Dim FormattedString as String = Join(Cisco_ShowLicenseArrayResults,EndOfLine.UNIX)
  
  License_RegExMatch = License_RegEx.Search(FormattedString)
  while License_RegExMatch <> nil
    if License_RegExMatch.SubExpressionString(1) <> "" Then
      Feature_HitText = License_RegExMatch.SubExpressionString(1)
    end if
    if License_RegExMatch.SubExpressionString(2) <> "" Then
      PeriodLeft_HitText = License_RegExMatch.SubExpressionString(2)
    end if
    License_RegExMatch = License_RegEx.Search
  Wend

Thank you so much Kem and Jim… I do appreciate the extra effort helping me on this! It appears that my Cisco device (as Jim mentioned earlier) is building my array dynamically differently (endofline) then the test code. The test code works perfectly so Ill get on streamlining the dynamically built array.

Once again you guys have gone above and beyond on this Forum!

Ok here is the discrepancies:

My Array that is built dynamically:

Yours (Works):

Notice the indentation differences :slight_smile: Thanks again guys!

Finally I rewrote the line endings and it now works with my dynamically built array. THANKS again!

  Dim License_RegEx as RegEx
  Dim License_RegExMatch as RegExMatch
  Dim Feature_HitText as String
  Dim PeriodLeft_HitText as String
  License_RegEx = New RegEx
  License_RegEx.Options.CaseSensitive = False
  License_RegEx.Options.Greedy = True
  License_RegEx.Options.MatchEmpty = True
  License_RegEx.Options.DotMatchAll = False
  License_RegEx.Options.StringBeginIsLineBegin = True
  License_RegEx.Options.StringEndIsLineEnd = True
  License_RegEx.Options.TreatTargetAsOneLine = False
  License_RegEx.SearchPattern = "(?mi-Us)Index\\s\\d\\sFeature:\\s(.*)\\s*Period\\sleft:\\s(.*)"
  
  Dim formattedstring, NewString as string 
  
  For i as integer = 0 to UBound(Cisco_ShowLicenseArrayResults)
    formattedstring = formattedstring + Cisco_ShowLicenseArrayResults(i)
  Next i
  
  NewString =ReplaceLineEndings(formattedstring,EndOfLine.UNIX)
  
  License_RegExMatch = License_RegEx.Search(NewString)
  while License_RegExMatch <> nil
    if License_RegExMatch.SubExpressionString(1) <> "" Then
      Feature_HitText = License_RegExMatch.SubExpressionString(1)
    end if
    if License_RegExMatch.SubExpressionString(2) <> "" Then
      PeriodLeft_HitText = License_RegExMatch.SubExpressionString(2)
    end if
    License_RegExMatch = License_RegEx.Search
  Wend

FYI, Join does what your loop does, but does it much faster. The problem is, your array contains the line endings already, so this should work for you instead:

formattedstring = Join( Cisco_ShowLicenseArrayResults, "" )
NewString = ReplaceLineEndings( formattedstring, EndOfLine.UNIX )

Awesome thanks Kem!