3

With Go, how would you determine if a string contains a certain string that includes wildcards? Example:

We're looking for t*e*s*t (the *'s can be any characters and any length of characters.

Input True: ttttteeeeeeeesttttttt

Input False: tset

2
  • 3
    Use a Regex - but if you really want globbing-style wildcards use a glob library like this one: github.com/gobwas/glob Commented Oct 24, 2020 at 2:57
  • Updated the formatting of the post. Commented Oct 24, 2020 at 17:30

2 Answers 2

6

Use the regexp package by converting the * in your pattern to the .* of regular expressions.

// wildCardToRegexp converts a wildcard pattern to a regular expression pattern.
func wildCardToRegexp(pattern string) string {
    var result strings.Builder
    for i, literal := range strings.Split(pattern, "*") {

        // Replace * with .*
        if i > 0 {
            result.WriteString(".*")
        }

        // Quote any regular expression meta characters in the
        // literal text.
        result.WriteString(regexp.QuoteMeta(literal))
    }
    return result.String()
}

Use it like this:

func match(pattern string, value string) bool {
    result, _ := regexp.MatchString(wildCardToRegexp(pattern), value)
    return result
}

Run it on the Go PlayGround.

Sign up to request clarification or add additional context in comments.

1 Comment

Thank you. It appears that this does the trick: ` package main import ( "fmt" "regexp" ) func main() { matched, err := regexp.MatchString(.*t.*e.*s.*t.*, "tttteeeessssstttttt") fmt.Println(matched, err) matched, err = regexp.MatchString(.*t.*e.*s.*t.*, "tset") fmt.Println(matched, err) }`
3

Good piece of code. I would offer one minor change. It seems to me that if you're using wildcards, then the absence of wildcards should mean exact match. To accomplish this, I use an early return....

func wildCardToRegexp(pattern string) string {
    components := strings.Split(pattern, "*")
    if len(components) == 1 {
        // if len is 1, there are no *'s, return exact match pattern
        return "^" + pattern + "$"
    }
    var result strings.Builder
    for i, literal := range components {

        // Replace * with .*
        if i > 0 {
            result.WriteString(".*")
        }

        // Quote any regular expression meta characters in the
        // literal text.
        result.WriteString(regexp.QuoteMeta(literal))
    }
    return "^" + result.String() + "$"
}

Run it on the Go Playground

3 Comments

the end result should also contain the "^" + ... + "$" pattern. Otherwise test* also matches 1test.
Good catch @RaphaelJenni I've updated the code and playground to include your feedback.
f len(components) == 1 { check if there's any *, but ignores other expression characters. I think we have to escape it before retruning: return "^" + regexp.QuoteMeta(pattern) + "$"

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.