skip regex chars until search using golang

Viewed 192

This will skip the 1st 2 characters and start matching left to right

re := regexp.MustCompile("(^.{2})(\\/path\\/subpath((\\/.*)|()))")
fmt.Println(re.MatchString("c:/path/subpath/path/subpath/")) // true
fmt.Println(re.MatchString("c:/patch/subpath/path/subpath/")) // false

notice the second one doesnt hit. even though /path/subpath exists in the string. This is perfect.

now if if dont know how many characters to skip and want to start search at the 1st '/' then i tried this

re2 := regexp.MustCompile("([^\\/])(\\/path\\/subpath((\\/.*)|()))")
fmt.Println(re2.MatchString("cddddd:/path/subpath/path/subpath"))  // true

which is perfect. but if i change the 1st path fmt.Println(re2.MatchString("cddddd:/patch/subpath/path/subpath")) // this is true as well

I don't want the last one to match the second /path/subpath. I want to be able to search in the 1st group, start the second group from there and do a left to right match.

Any help would be great appreciated.

1 Answers

It pays to be more precise about what you want, state what you want in absolute terms, not like "second first should not match third". Instead, say;

I want to capture the path if it begins with /path/subpath in the second group. If a path contains /path/subpath somewhere in later than the beginning, then I don't want that to match.

Also, slashes are not special in regex, so you don't need to double-escape them for nothing.

The third expression, does this:

  1. capture everything that is not a slash from the start anchor
  2. delimit group 1 from group 2 by :
  3. require /path/subpath to be the at the top of the path
  4. capture whatever remains

This may be what you want:

package main

import (
    "fmt"
    "regexp"
)

func main() {
    paths := []string{
        "c:/path/subpath/path/subpath/",
        "c:/patch/subpath/path/subpath/",
        "cddddd:/path/subpath/path/subpath",
    }

    re1 := regexp.MustCompile("(^.{2})(/path/subpath(/.*))")
    re2 := regexp.MustCompile("([^/])(/path/subpath((/.*)|()))")
    re3 := regexp.MustCompile(`^([^/]+):/path/subpath(/.*)`)

    for i, re := range []*regexp.Regexp{re1, re2, re3} {
        i++
        for _, s := range paths {
            fmt.Println(i, re.MatchString(s), s)
            if re.MatchString(s) {
                matches := re.FindStringSubmatch(s)
                for m, g := range matches {
                    m++
                    if m > 1 {
                        fmt.Printf("\n\t%d %v", m, g)
                    }
                }
            }
            println()
        }
        println()
    }
}

Output

$ go run so-regex-path.go 
(...)

3 true c:/path/subpath/path/subpath/

    2 c
    3 /path/subpath/
3 false c:/patch/subpath/path/subpath/

3 true cddddd:/path/subpath/path/subpath

    2 cddddd
    3 /path/subpath
Related