package main import ( //"fmt" "path" "strings" "unicode/utf8" "regexp" ) var ErrBadPattern = path.ErrBadPattern func main(){ match, _ := ExpMatch("linux*","linux1") println(match) match, _ = regexp.MatchString("linux.*?","linux1") println("regexp ==>", match) match, _ = ExpMatch("linux?","linux1") println(match) match, _ = regexp.MatchString("linux.","linux1") println("regexp ==>", match) match, _ = ExpMatch("linux[1-2]","linux1") println(match) match, _ = regexp.MatchString("linux[1-2]","linux1") println("regexp ==>", match) match, _ = ExpMatch("linux[12]","linux1") println(match) match, _ = regexp.MatchString("linux[12]","linux1") println("regexp ==>", match) match, _ = ExpMatch("linux[^2345]","linux1") println(match) match, _ = regexp.MatchString("linux[^2345]","linux1") println("regexp ==>", match) println("----------------------") match, _ = ExpMatch("linux[^12345]","linux1") println(match) match, _ = regexp.MatchString("linux[^12345]","linux1") println("regexp ==>", match) match, _ = ExpMatch("linux*[^12345]","linux1") println(match) match, _ = regexp.MatchString("linux.*?[^12345]","linux1") println("regexp ==>", match) match, _ = ExpMatch("中文*","中文测试") println(match) match, _ = regexp.MatchString("中文*","中文测试") println("regexp ==>", match) match, _ = ExpMatch("中文??","中文测试") println(match) match, _ = regexp.MatchString("中文..","中文测试") println("regexp ==>", match) srp := strings.NewReplacer("?", ".", "*", ".*?") s := "linux*?" print( "replace ==>", srp.Replace(s) ) } func ExpMatch(pattern, name string) (bool, error) { // check some base cases patternLen, nameLen := len(pattern), len(name) if patternLen == 0 && nameLen == 0 { return true, nil } if patternLen == 0 { return false, nil } if nameLen == 0 && pattern != "*" { return false, nil } // check for matches one rune at a time patIdx, nameIdx := 0, 0 for patIdx < patternLen && nameIdx < nameLen { patRune, patAdj := utf8.DecodeRuneInString(pattern[patIdx:]) nameRune, nameAdj := utf8.DecodeRuneInString(name[nameIdx:]) if patRune == '\\' { // handle escaped runes patIdx += patAdj patRune, patAdj = utf8.DecodeRuneInString(pattern[patIdx:]) if patRune == utf8.RuneError { return false, ErrBadPattern } else if patRune == nameRune { patIdx += patAdj nameIdx += nameAdj } else { return false, nil } } else if patRune == '*' { // handle stars if patIdx += patAdj; patIdx >= patternLen { // a star at the end of a pattern will always // match the rest of the path return true, nil } // check if we can make any matches for ; nameIdx < nameLen; nameIdx += nameAdj { if m, _ := ExpMatch(pattern[patIdx:], name[nameIdx:]); m { return true, nil } } return false, nil } else if patRune == '[' { // handle character sets patIdx += patAdj endClass := indexRuneWithEscaping(pattern[patIdx:], ']') if endClass == -1 { return false, ErrBadPattern } endClass += patIdx classRunes := []rune(pattern[patIdx:endClass]) classRunesLen := len(classRunes) if classRunesLen > 0 { classIdx := 0 matchClass := false if classRunes[0] == '^' { classIdx++ } for classIdx < classRunesLen { low := classRunes[classIdx] if low == '-' { return false, ErrBadPattern } classIdx++ if low == '\\' { if classIdx < classRunesLen { low = classRunes[classIdx] classIdx++ } else { return false, ErrBadPattern } } high := low if classIdx < classRunesLen && classRunes[classIdx] == '-' { // we have a range of runes if classIdx++; classIdx >= classRunesLen { return false, ErrBadPattern } high = classRunes[classIdx] if high == '-' { return false, ErrBadPattern } classIdx++ if high == '\\' { if classIdx < classRunesLen { high = classRunes[classIdx] classIdx++ } else { return false, ErrBadPattern } } } if low <= nameRune && nameRune <= high { matchClass = true } } if matchClass == (classRunes[0] == '^') { return false, nil } } else { return false, ErrBadPattern } patIdx = endClass + 1 nameIdx += nameAdj }else if patRune == '?' || patRune == nameRune { // handle single-rune wildcard patIdx += patAdj nameIdx += nameAdj } else { return false, nil } } if patIdx >= patternLen && nameIdx >= nameLen { return true, nil } if nameIdx >= nameLen && pattern[patIdx:] == "*" || pattern[patIdx:] == "**" { return true, nil } return false, nil } // Find the first index of a rune in a string, // ignoring any times the rune is escaped using "\". func indexRuneWithEscaping(s string, r rune) int { end := strings.IndexRune(s, r) if end == -1 { return -1 } if end > 0 && s[end-1] == '\\' { start := end + utf8.RuneLen(r) end = indexRuneWithEscaping(s[start:], r) if end != -1 { end += start } } return end }