Snippet String function - Wildcard pattern matching

AceHart

Your Friendly Neighborhood Admin
Reaction score
1,495
JASS:
function match takes string text,string mask,boolean case returns boolean
    local string a
    local string b
    local string x
    local string y
    local integer i = 0
    local integer j = 0
    local boolean m

    if case then
        set a = text
        set b = mask
    else
        set a = StringCase(text, true)
        set b = StringCase(mask, true)
    endif

    set x = SubString(a, 0, 1)
    set y = SubString(b, 0, 1)
    if x == null and y == null then
        return false
    endif

    loop
        if y == null then
            return x == null
        elseif y == "#" then
            exitwhen not (x == "0" or x == "1" or x == "2" or x == "3" or x == "4" or x == "5" or x == "6" or x == "7" or x == "8" or x == "9")
        elseif y == "\\" then
            set j = j + 1
            set y = SubString(b, j, j + 1)
            exitwhen x != y
        elseif y == "?" then
            // nothing to do
        elseif y == "[" then
            set j = j + 1
            set y = SubString(b, j, j + 1)
            exitwhen y == null
            set m = false
            if y == "!" then
                loop
                    set j = j + 1
                    set y = SubString(b, j, j + 1)
                    if y == null then
                        return false
                    endif
                    exitwhen y == "]"
                    if x == y then
                        set m = true
                    endif
                endloop
                exitwhen y != "]"
                exitwhen m == true
            else
                loop
                    if y == null then
                        return false
                    endif
                    if x == y then
                        set m = true
                    endif
                    set j = j + 1
                    set y = SubString(b, j, j + 1)
                    exitwhen y == "]"
                endloop
                exitwhen y != "]"
                exitwhen m == false
            endif
        elseif y == "*" then
            loop
                set j = j + 1
                set y = SubString(b, j, j + 1)
                exitwhen y != "*"
            endloop
//          if y == null then
            if StringLength(y) < 1 then
                return true
            endif
            set a = SubString(a, i, StringLength(a))
            set b = SubString(b, j, StringLength(b))
            loop
                exitwhen a == null
                if match(a, b, case) then
                    return true
                endif
                set i = i + 1
                set a = SubString(a, 1, StringLength(a))
            endloop
            return false
        else
            exitwhen x != y
        endif

        set i = i + 1
        set j = j + 1
        set x = SubString(a, i, i + 1)
        set y = SubString(b, j, j + 1)
    endloop
    return false
endfunction



Basic case (in)sensitive pattern matching.

Supported wildcard characters:
* - matches 0 or more any characters
? - matches exactly 1 any character
# - matches any digit, 0-9
[noparse]
  • [/noparse] - matches any character in <list> (l, i, s and t in this example)
    [!list] - matches any character that isn't in the list


    Use \\* or \\? or \\[ to match a * or ? or [ respectively.
    To get a ] in a list, put it as first character of the list.
    To get a ! in a list, don't put it first.
    By common convention, special characters *, ? and # have no meaning when used in a list.

    If "case" is true, the matching is case sensitive.


    Examples:
    Code:
    match("AceHart", "", case) returns false
    match("AceHart", "*", case) returns true
    match("AceHart", "*acehart*", false) returns true
    match("AceHart", "*e*", case) returns true
    match("AceHart", "**test**", case) returns false
    match("AceHart", "Ace?art") returns true
    
    match("Gray", "gr[ea]y", false) returns true
    
    "####" matches any 4 digits
    "[!0123456789]" matches any character that is not a digit
 

cr4xzZz

Also known as azwraith_ftL.
Reaction score
51
Hmm, nice. :thup:

> match("AceHart", "AceH") returns false
Why would this return false? I thought it has 4 matches...
 

Kenny

Back for now.
Reaction score
202
Why would this return false? I thought it has 4 matches...

Because it is only 4 letters long in total. It has no * or ? so it has a max of 4 letters, which will not match with AceHeart.

* - matches 0 or more any characters
? - matches exactly 1 any character

Nice work btw.:thup:
 

AceHart

Your Friendly Neighborhood Admin
Reaction score
1,495
> I thought it has 4 matches

It matches the first 4 characters, but it doesn't match the entire string. The "art" part is missing.


> which will not match with AceHeart.

That is no match for AceHart either :p
 

Troll-Brain

You can change this now in User CP.
Reaction score
85
It seems using null instead of an empty string "" can fuck up the loop, making more iterations that needed.
 

martix

There is no spoon
Reaction score
49
I wonder what a regex engine could be used for... This goes some of the way, but I don't know how possible a complete one is :)
 

AceHart

Your Friendly Neighborhood Admin
Reaction score
1,495
Everybody needs one!


JASS:
if match(GetEventPlayerChatString(), &quot;-kick gr[ea]y&quot;, false) == true then
    ...


if match(GetEventPlayerChatString(), GetEventPlayerChatStringMatched() + &quot; ####&quot;, false) == true then
    call DisplayTextToPlayer(GetLocalPlayer(), 0, 0, &quot;I expected a 4 digits number here...&quot;)


if match(GetEventPlayerChatString(), GetEventPlayerChatStringMatched(), false) == true then
    call DisplayTextToPlayer(GetLocalPlayer(), 0, 0, &quot;You forgot the parameter&quot;)
elseif match(GetEventPlayerChatString(), GetEventPlayerChatStringMatched() + &quot; ?&quot;, false) == false then
    call DisplayTextToPlayer(GetLocalPlayer(), 0, 0, &quot;Still not enough&quot;)
elseif match(GetEventPlayerChatString(), GetEventPlayerChatStringMatched() + &quot; ?&quot;, true) == false then
    call DisplayTextToPlayer(GetLocalPlayer(), 0, 0, &quot;We&#039;re picky! Case-sensitive only!&quot;)
endif

Well :p


Someone over at wc3campaigns presumably started "The Complete".
How far he actually gets remains to be seen.

This has its uses, works, and is very simple.
 

AceHart

Your Friendly Neighborhood Admin
Reaction score
1,495
> You might mention that it doesn't compile.

"Works here(tm)"


> add or "" with the null checking ?

Once I get around to figuring out where exactly that can be done, or really shouldn't be done.
Until then, I prefer something that actually works, even though it wastes a couple CPU cycles.
 
Reaction score
456
> * - matches 0 or more any characters
Can you add matches one or more any characters? And zero or one.
 
General chit-chat
Help Users
  • No one is chatting at the moment.

      The Helper Discord

      Members online

      No members online now.

      Affiliates

      Hive Workshop NUON Dome World Editor Tutorials

      Network Sponsors

      Apex Steel Pipe - Buys and sells Steel Pipe.
      Top