B4J Question [SOLVED] Regex problem: Why does my code not match anything, but Erel's Online-Tool does?

bububrln

Member
Licensed User
Hello everyone,

I am trying to find a certain substring in a given string using an regular expression. As an example, I've been using one of the JSON examples on this site, but already stripped from any insignificant whitespace (i.e. whitespace not inside quotes). My aim is to find the first word that is enclosed in quotes an followed by a colon. For that, I am using
as regex pattern.

Unfortunately, my code below doesn't work - it crashes, because apparently there's no match to be found:

find match using regex:
Dim source As String = $"{"menu":{"id":"file","value":"File","popup":{"menuitem":[{"value":"New","onclick":"CreateNewDoc()"},{"value":"Open","onclick":"OpenDoc()"},{"value":"Close","onclick":"CloseDoc()"}]}}}"$
Dim m As Matcher = Regex.Matcher2($""\w+":"$, source) ' Find occurances of a word that has quotes around it and is being followed by a colon
Dim match As String
match = m.Match  
Log (match.SubString2(1, match.Length -2)) ' Return it without the quotes and the colon

I would have expected it to find
(and all the others) and thus log
as first match. Sadly, it doesn't :) And interestingly, the very same string gets parsed just as expected using the same regex pattern when doing so via Erel's interactive tool: https://b4x.com:51041/regex_ws/index.html:

screenshot.png


Does anybody have a clue what I am doing wrong here?

Thanks!
 

drgottjr

Expert
Licensed User
Longtime User
works if you change Regex.Matcher2 to Regex.Matcher. RegexMatcher2 is a different call.
also, you should never assume there is going to be a match. before assigning your string match, you should test:
B4X:
if m.find then
   match = m.match
else
   match = "no match"
end if
log (match)
 
Upvote 0

bububrln

Member
Licensed User
Thank you! Actually, I was initially using Regex.Matcher (without the 2), but it crashed just as described. The code above is - sorry for the error - a mixture of my first try and the second also unsuccessful one using match2 and a zero as option (not shown here).

Does this work for you (i.e. match something) when using match rather than match2? It did not find anything for me...

So while I agree that I should have cought "non-matches", I still cannot grasp why this does not find something...
 
Upvote 0

Daestrum

Expert
Licensed User
Longtime User
B4X:
    Dim source As String = $"{"menu":{"id":"file","value":"File","popup":{"menuitem":[{"value":"New","onclick":"CreateNewDoc()"},{"value":"Open","onclick":"OpenDoc()"},{"value":"Close","onclick":"CloseDoc()"}]}}}"$
    Dim m As Matcher = Regex.Matcher($""\w+":"$, source) ' Find occurances of a word that has quotes around it and is being followed by a colon
    
    Do While m.Find
        Dim match As String = m.Match
        Log (match.SubString2(1, match.Length -2)) ' Return it without the quotes and the colon
    Loop
 
Upvote 0

drgottjr

Expert
Licensed User
Longtime User
Does this work for you (i.e. match something) when using match rather than match2? It did not find anything for me...

as i said, your code worked when i changed regex.matcher2 to reges.matcher (see attached image. the word "menu" appears in the log on the righthand side.

beyond getting rid of regex.matcher2 (which was obvious immediately), i tried regex.matcher 2 different ways: once with erel's smart string and once the old-fashioned way. both worked. can't say why it doesn't work for you. i copied and pasted your code.
 

Attachments

  • regex.png
    regex.png
    16.1 KB · Views: 146
Upvote 0

bububrln

Member
Licensed User
Thanks to both of you! As it turns out, there was one essential step missing in my code: I did not actually perform the regex based search 🤦‍, and therefore the result had to be non-exstistant... I understood this when I replicated drgottjr's code and found out that it is the
that, well, finds the matches. So, if one for some reason decides not to handle the case that there might be no match, the following still works fine:

B4X:
Dim source As String = $"{"menu":{"id":"file","value":"File","popup":{"menuitem":[{"value":"New","onclick":"CreateNewDoc()"},{"value":"Open","onclick":"OpenDoc()"},{"value":"Close","onclick":"CloseDoc()"}]}}}"$
Dim m As Matcher = Regex.Matcher($""\w+":"$, source) ' Find the first occurance of a word that has quotes around it and is being followed by a colon
m.Find ' <-- This performs the actual search!
Log (m.Match.SubString2(1, m.Match.Length -2)) ' Return in without the quotes and the colon

Obviously, this would still crash if there was no match, so I'd have it default to an empty string in that case:

B4X:
Dim source As String = $"{"menu":{"id":"file","value":"File","popup":{"menuitem":[{"value":"New","onclick":"CreateNewDoc()"},{"value":"Open","onclick":"OpenDoc()"},{"value":"Close","onclick":"CloseDoc()"}]}}}"$
Dim m As Matcher = Regex.Matcher($""\w+":"$, source) ' Find the first occurance of a word that has quotes around it and is being followed by a colon  
Dim result As String = ""
If m.Find Then result = m.Match.SubString2(1, m.Match.Length -2) ' without the quotes and the colon
Log (result)

Anyway - I didn't call m.find in my initial code at all, and that's why it failed. Mystery solved.
 
Last edited:
Upvote 0
Top