2 回答

TA貢獻(xiàn)1785條經(jīng)驗(yàn) 獲得超4個(gè)贊
您的正則表達(dá)式似乎有兩個(gè)主要問題,其中一個(gè)比另一個(gè)更容易處理:
正則表達(dá)式天生就不擅長(zhǎng)處理遞歸匹配,例如分組左括號(hào)和右括號(hào),因?yàn)樗鼈儧]有內(nèi)存。就您而言,我認(rèn)為您已嘗試通過(guò)將自己限制在一些特定情況下來(lái)解決此問題,但正則表達(dá)式的貪婪性質(zhì)在這里對(duì)您不利。
您不匹配右括號(hào)前可能有空格的情況。
這兩個(gè)問題一起導(dǎo)致您的正則表達(dá)式在這兩種情況下失敗,但也導(dǎo)致您的第一個(gè)案例匹配。
要解決此問題,您必須在將字符串發(fā)送到正則表達(dá)式之前對(duì)字符串進(jìn)行一些預(yù)處理:
if strings.HasPrefix(rawSql, "(") { rawSql = rawSql[1:len(rawSql) - 1] }
這將去掉任何外括號(hào),如果沒有內(nèi)存或額外的子句,正則表達(dá)式將無(wú)法忽略這些括號(hào)。
接下來(lái),您需要修改正則表達(dá)式以處理內(nèi)部函數(shù)調(diào)用和$__timeFilter
調(diào)用之間可能存在空格的情況:
func getRegex(name string) string { return fmt.Sprintf("\\$__%s\\b(\\((.*?\\)?)\\s*\\))?", name) }
這樣做之后,您的正則表達(dá)式應(yīng)該可以工作了。您可以在此 playground 鏈接上找到完整示例。

TA貢獻(xiàn)1797條經(jīng)驗(yàn) 獲得超6個(gè)贊
盡管我最終不得不走另一條路,但我還是選擇了 Woody 的答案作為正確答案。附加的測(cè)試用例不包括某些場(chǎng)景,結(jié)果我還必須能夠提取括號(hào)內(nèi)的參數(shù)。所以這是我的最終解決方案,我手動(dòng)解析文本,找到邊界括號(hào)并提取它們之間的任何內(nèi)容:
// getMacroMatches extracts macro strings with their respective arguments from the sql input given
// It manually parses the string to find the closing parenthesis of the macro (because regex has no memory)
func getMacroMatches(input string, name string) ([][]string, error) {
macroName := fmt.Sprintf("\\$__%s\\b", name)
matchedMacros := [][]string{}
rgx, err := regexp.Compile(macroName)
if err != nil {
return nil, err
}
// get all matching macro instances
matched := rgx.FindAllStringIndex(input, -1)
if matched == nil {
return nil, nil
}
for matchedIndex := 0; matchedIndex < len(matched); matchedIndex++ {
var macroEnd = 0
var argStart = 0
macroStart := matched[matchedIndex][0]
inputCopy := input[macroStart:]
cache := make([]rune, 0)
// find the opening and closing arguments brackets
for idx, r := range inputCopy {
if len(cache) == 0 && macroEnd > 0 {
break
}
switch r {
case '(':
cache = append(cache, r)
if argStart == 0 {
argStart = idx + 1
}
case ')':
l := len(cache)
if l == 0 {
break
}
cache = cache[:l-1]
macroEnd = idx + 1
default:
continue
}
}
// macroEnd equals to 0 means there are no parentheses, so just set it
// to the end of the regex match
if macroEnd == 0 {
macroEnd = matched[matchedIndex][1] - macroStart
}
macroString := inputCopy[0:macroEnd]
macroMatch := []string{macroString}
args := ""
// if opening parenthesis was found, extract contents as arguments
if argStart > 0 {
args = inputCopy[argStart : macroEnd-1]
}
macroMatch = append(macroMatch, args)
matchedMacros = append(matchedMacros, macroMatch)
}
return matchedMacros, nil
}
游樂場(chǎng)鏈接:https://go.dev/play/p/-odWKMBLCBv
- 2 回答
- 0 關(guān)注
- 210 瀏覽
添加回答
舉報(bào)