第七色在线视频,2021少妇久久久久久久久久,亚洲欧洲精品成人久久av18,亚洲国产精品特色大片观看完整版,孙宇晨将参加特朗普的晚宴

為了賬號(hào)安全,請(qǐng)及時(shí)綁定郵箱和手機(jī)立即綁定
已解決430363個(gè)問題,去搜搜看,總會(huì)有你想問的

Go 的正則表達(dá)式,匹配包含平衡括號(hào)的內(nèi)容

Go 的正則表達(dá)式,匹配包含平衡括號(hào)的內(nèi)容

Go
子衿沉夜 2023-02-28 20:20:18
所以我的用例如下:我正在解析一個(gè) SQL 查詢,試圖獲取函數(shù)名稱和發(fā)送到該函數(shù)的各個(gè)參數(shù)。這要求我的正則表達(dá)式能夠找到名稱、左括號(hào)、內(nèi)容和右括號(hào)。不幸的是,在測(cè)試時(shí)發(fā)現(xiàn)它有時(shí)過(guò)于貪婪,抓住額外的括號(hào)而其他時(shí)候它錯(cuò)過(guò)了結(jié)束的括號(hào)。這是我在操場(chǎng)上的測(cè)試代碼:func getRegex(name string) string {    return fmt.Sprintf("\\$__%s\\b(?:\\((.*?\\)?)\\))?", name)}func main() {    var rawSQL = "(select min(time) from table where $__timeFilter(time))"    rgx, err := regexp.Compile(getRegex("timeFilter"))    if err != nil {        fmt.Println(err)    }    var match = rgx.FindAllStringSubmatch(rawSQL, -1)    fmt.Println(match)}舉個(gè)例子https://go.dev/play/p/4FpZblia7Ks我測(cè)試的4個(gè)案例如下:(select min(time) from table where $__timeFilter(time) ) OK(select min(time) from table where $__timeFilter(time)) NOKselect * from foo where $__timeFilter(cast(sth as timestamp)) OKselect * from foo where $__timeFilter(cast(sth as timestamp) ) NOK這是一個(gè)實(shí)時(shí)正則表達(dá)式版本https://regexr.com/700oh我來(lái)自 javascript 世界,所以從未使用過(guò)遞歸正則表達(dá)式,看起來(lái)這可能是一種情況?
查看完整描述

2 回答

?
九州編程

TA貢獻(xiàn)1785條經(jīng)驗(yàn) 獲得超4個(gè)贊

您的正則表達(dá)式似乎有兩個(gè)主要問題,其中一個(gè)比另一個(gè)更容易處理:

  1. 正則表達(dá)式天生就不擅長(zhǎng)處理遞歸匹配,例如分組左括號(hào)和右括號(hào),因?yàn)樗鼈儧]有內(nèi)存。就您而言,我認(rèn)為您已嘗試通過(guò)將自己限制在一些特定情況下來(lái)解決此問題,但正則表達(dá)式的貪婪性質(zhì)在這里對(duì)您不利。

  2. 您不匹配右括號(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 鏈接上找到完整示例。


查看完整回答
反對(duì) 回復(fù) 2023-02-28
?
FFIVE

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


查看完整回答
反對(duì) 回復(fù) 2023-02-28
  • 2 回答
  • 0 關(guān)注
  • 210 瀏覽
慕課專欄
更多

添加回答

舉報(bào)

0/150
提交
取消
微信客服

購(gòu)課補(bǔ)貼
聯(lián)系客服咨詢優(yōu)惠詳情

幫助反饋 APP下載

慕課網(wǎng)APP
您的移動(dòng)學(xué)習(xí)伙伴

公眾號(hào)

掃描二維碼
關(guān)注慕課網(wǎng)微信公眾號(hào)