golang 正則表達(dá)式

package main


import (
    "fmt"
    "regexp"
)


func main() {
    text := `<p>更多分析師觀點詳見&nbsp;
<a  target="_blank" rel="noopener">
一周策略前瞻:周期之火破滅了蔓彩?</a></p>
<p><strong>來看主題:</strong></p>
<p><strong>
1治笨、<a class="" >PPP</a>&nbsp;:
</strong>
<a  target="_blank" rel="noopener">
國辦發(fā)文力促民資參與PPP,經(jīng)濟(jì)回落下行業(yè)有望再成>穩(wěn)增長抓手&nbsp;</a></p>
<p>參見上文邏輯赤嚼,此處不多說了旷赖。地產(chǎn)板塊也是類似。</p>`

    //var SubjectRegexp = regexp.MustCompile(`<a href="https://[[:ascii:]]*">(?P<ct>.*)</a>`)
    var ArticleRegexp = regexp.MustCompile(`<a.*href="https://(m|api).xxx.cn(.*)/(article|subjects)/[\d]+"(.*)>(.+)</a>`)
    fmt.Println(ArticleRegexp.FindAllString(text, -1))
    //fmt.Println(SubjectRegexp.FindAllString(text, -1))
    //fmt.Println(SubjectRegexp.ReplaceAllString(text, `${ct}`))
    text2 := `I'm singing while you're dancing.`
    RegExpIng := regexp.MustCompile(`((\')\w{1,2})`)
    fmt.Println(RegExpIng.FindAllString(text2, -1))
}

Output:

[<a  target="_blank" rel="noopener">一周策略前瞻:周期之火破滅了更卒?</a> <a class="" >PPP</a>&nbsp;:</strong><a  target="_blank" rel="noopener">國辦發(fā)文力促民資參與PPP等孵,經(jīng)濟(jì)回落下行業(yè)有望再成穩(wěn)增長抓手&nbsp;</a>]
['m 're]

1.MustCompile(...) VS Compile(...)

func Compile(expr string) (*Regexp, error) {
    return compile(expr, syntax.Perl, false)
}

MustComile實際上調(diào)用的是Compile。加了錯誤檢測蹂空。

func MustCompile(str string) *Regexp {
    regexp, error := Compile(str)
    if error != nil {
        panic(`regexp: Compile(` + quote(str) + `): ` + error.Error())
    }
    return regexp
}

2. MatchString檢測是否匹配正則俯萌,參數(shù)為被檢測的字符串,返回布爾值

// MatchString reports whether the string s
// contains any match of the regular expression re.
func (re *Regexp) MatchString(s string) bool {
    return re.doMatch(nil, nil, s)
}

3. FindAllString(...)

有兩個參數(shù)腌闯,第一個參數(shù)為要處理的字符串绳瘟,第二個參數(shù)獲取匹配的結(jié)果數(shù)量,如果為負(fù)數(shù)姿骏,則取出所有滿足條件的匹配結(jié)果

// FindAllString is the 'All' version of FindString; it returns a slice of all
// successive matches of the expression, as defined by the 'All' description
// in the package comment.
// A return value of nil indicates no match.
func (re *Regexp) FindAllString(s string, n int) []string {
    if n < 0 {
        n = len(s) + 1
    }
    result := make([]string, 0, startSize)
    re.allMatches(s, nil, n, func(match []int) {
        result = append(result, s[match[0]:match[1]])
    })
    if len(result) == 0 {
        return nil
    }
    return result
}

其中核心是調(diào)用了 allMatches的私有方法獲取的結(jié)果糖声。該方法的第一個參數(shù)為要處理的文本字符串,第二個參數(shù)為字節(jié)數(shù)字切片分瘦,在FindAllString中使用的空指針蘸泻。第三個參數(shù)為FindAllString的第二個參數(shù)n,第四個參數(shù)為一個函數(shù),它負(fù)責(zé)把所有的收集嘲玫。

// Find matches in slice b if b is non-nil, otherwise find matches in string s.
func (re *Regexp) allMatches(s string, b []byte, n int, deliver func([]int)) {
    var end int
    if b == nil {
        end = len(s)
    } else {
        end = len(b)
    }

    for pos, i, prevMatchEnd := 0, 0, -1; i < n && pos <= end; {
        matches := re.doExecute(nil, b, s, pos, re.prog.NumCap, nil)
        if len(matches) == 0 {
            break
        }

        accept := true
        if matches[1] == pos {
            // We've found an empty match.
            if matches[0] == prevMatchEnd {
                // We don't allow an empty match right
                // after a previous match, so ignore it.
                accept = false
            }
            var width int
            // TODO: use step()
            if b == nil {
                _, width = utf8.DecodeRuneInString(s[pos:end])
            } else {
                _, width = utf8.DecodeRune(b[pos:end])
            }
            if width > 0 {
                pos += width
            } else {
                pos = end + 1
            }
        } else {
            pos = matches[1]
        }
        prevMatchEnd = matches[1]

        if accept {
            deliver(re.pad(matches))
            i++
        }
    }
}
re := regexp.MustCompile("a.")
fmt.Println(re.FindAllString("paranormal", -1))
fmt.Println(re.FindAllString("paranormal", 2))
fmt.Println(re.FindAllString("graal", -1))
fmt.Println(re.FindAllString("none", -1))

Output:

[ar an al]
[ar an]
[aa]
[]

4.ReplaceAllString(...)

替換所有匹配到的結(jié)果為指定的字符串悦施。第二個參數(shù)給出了要替換的值

func (re *Regexp) ReplaceAllString(src, repl string) string {
    n := 2
    if strings.Contains(repl, "$") {
        n = 2 * (re.numSubexp + 1)
    }
    b := re.replaceAll(nil, src, n, func(dst []byte, match []int) []byte {
        return re.expand(dst, repl, nil, src, match)
    })
    return string(b)
}

replaceAll

func (re *Regexp) replaceAll(bsrc []byte, src string, nmatch int, repl func(dst []byte, m []int) []byte) []byte {
    lastMatchEnd := 0 // end position of the most recent match
    searchPos := 0    // position where we next look for a match
    var buf []byte
    var endPos int
    if bsrc != nil {
        endPos = len(bsrc)
    } else {
        endPos = len(src)
    }
    if nmatch > re.prog.NumCap {
        nmatch = re.prog.NumCap
    }

    var dstCap [2]int
    for searchPos <= endPos {
        a := re.doExecute(nil, bsrc, src, searchPos, nmatch, dstCap[:0])
        if len(a) == 0 {
            break // no more matches
        }

        // Copy the unmatched characters before this match.
        if bsrc != nil {
            buf = append(buf, bsrc[lastMatchEnd:a[0]]...)
        } else {
            buf = append(buf, src[lastMatchEnd:a[0]]...)
        }

        // Now insert a copy of the replacement string, but not for a
        // match of the empty string immediately after another match.
        // (Otherwise, we get double replacement for patterns that
        // match both empty and nonempty strings.)
        if a[1] > lastMatchEnd || a[0] == 0 {
            buf = repl(buf, a)
        }
        lastMatchEnd = a[1]

        // Advance past this match; always advance at least one character.
        var width int
        if bsrc != nil {
            _, width = utf8.DecodeRune(bsrc[searchPos:])
        } else {
            _, width = utf8.DecodeRuneInString(src[searchPos:])
        }
        if searchPos+width > a[1] {
            searchPos += width
        } else if searchPos+1 > a[1] {
            // This clause is only needed at the end of the input
            // string. In that case, DecodeRuneInString returns width=0.
            searchPos++
        } else {
            searchPos = a[1]
        }
    }

    // Copy the unmatched characters after the last match.
    if bsrc != nil {
        buf = append(buf, bsrc[lastMatchEnd:]...)
    } else {
        buf = append(buf, src[lastMatchEnd:]...)
    }

    return buf
}

5. ReplaceAllStringFunc

func ConvertTabToEmptyString(text string) string {
    return TabRegExp.ReplaceAllStringFunc(text, func(matchedStr string) string {
        return strings.Replace(matchedStr, "   ", " ", -1)
    })
}

6.FindAllStringSubmatch

找出有匹配到的字符串子組列表,第二個參數(shù)小于0去团,表示全部匹配

// FindAllStringSubmatch is the 'All' version of FindStringSubmatch; it
// returns a slice of all successive matches of the expression, as defined by
// the 'All' description in the package comment.
// A return value of nil indicates no match.
func (re *Regexp) FindAllStringSubmatch(s string, n int) [][]string {
    if n < 0 {
        n = len(s) + 1
    }
    var result [][]string
    re.allMatches(s, nil, n, func(match []int) {
        if result == nil {
            result = make([][]string, 0, startSize)
        }
        slice := make([]string, len(match)/2)
        for j := range slice {
            if match[2*j] >= 0 {
                slice[j] = s[match[2*j]:match[2*j+1]]
            }
        }
        result = append(result, slice)
    })
    return result
}

示例:

func AlliRemLinkUrls(articleArr []*Article) {
    for _, article := range articleArr {
        if strArrArr := LinkUrlRegExp.FindAllStringSubmatch(article.Content, -1); strArrArr != nil {
            for _, strArr := range strArrArr {
                article.Content = strings.Replace(article.Content, strArr[0], strArr[3], 1)
            }
        }
    }
}
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末抡诞,一起剝皮案震驚了整個濱河市,隨后出現(xiàn)的幾起案子土陪,更是在濱河造成了極大的恐慌昼汗,老刑警劉巖,帶你破解...
    沈念sama閱讀 222,590評論 6 517
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件鬼雀,死亡現(xiàn)場離奇詭異顷窒,居然都是意外死亡,警方通過查閱死者的電腦和手機(jī)源哩,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 95,157評論 3 399
  • 文/潘曉璐 我一進(jìn)店門鞋吉,熙熙樓的掌柜王于貴愁眉苦臉地迎上來鸦做,“玉大人,你說我怎么就攤上這事谓着∑糜眨” “怎么了?”我有些...
    開封第一講書人閱讀 169,301評論 0 362
  • 文/不壞的土叔 我叫張陵漆魔,是天一觀的道長坷檩。 經(jīng)常有香客問我却音,道長改抡,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 60,078評論 1 300
  • 正文 為了忘掉前任系瓢,我火速辦了婚禮阿纤,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘夷陋。我一直安慰自己欠拾,他們只是感情好,可當(dāng)我...
    茶點故事閱讀 69,082評論 6 398
  • 文/花漫 我一把揭開白布骗绕。 她就那樣靜靜地躺著藐窄,像睡著了一般。 火紅的嫁衣襯著肌膚如雪酬土。 梳的紋絲不亂的頭發(fā)上荆忍,一...
    開封第一講書人閱讀 52,682評論 1 312
  • 那天,我揣著相機(jī)與錄音撤缴,去河邊找鬼刹枉。 笑死,一個胖子當(dāng)著我的面吹牛屈呕,可吹牛的內(nèi)容都是我干的微宝。 我是一名探鬼主播,決...
    沈念sama閱讀 41,155評論 3 422
  • 文/蒼蘭香墨 我猛地睜開眼虎眨,長吁一口氣:“原來是場噩夢啊……” “哼蟋软!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起嗽桩,我...
    開封第一講書人閱讀 40,098評論 0 277
  • 序言:老撾萬榮一對情侶失蹤岳守,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后涤躲,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體棺耍,經(jīng)...
    沈念sama閱讀 46,638評論 1 319
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 38,701評論 3 342
  • 正文 我和宋清朗相戀三年种樱,在試婚紗的時候發(fā)現(xiàn)自己被綠了蒙袍。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片俊卤。...
    茶點故事閱讀 40,852評論 1 353
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖害幅,靈堂內(nèi)的尸體忽然破棺而出消恍,到底是詐尸還是另有隱情,我是刑警寧澤以现,帶...
    沈念sama閱讀 36,520評論 5 351
  • 正文 年R本政府宣布狠怨,位于F島的核電站,受9級特大地震影響邑遏,放射性物質(zhì)發(fā)生泄漏佣赖。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點故事閱讀 42,181評論 3 335
  • 文/蒙蒙 一记盒、第九天 我趴在偏房一處隱蔽的房頂上張望憎蛤。 院中可真熱鬧,春花似錦纪吮、人聲如沸俩檬。這莊子的主人今日做“春日...
    開封第一講書人閱讀 32,674評論 0 25
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽棚辽。三九已至,卻和暖如春冰肴,著一層夾襖步出監(jiān)牢的瞬間屈藐,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 33,788評論 1 274
  • 我被黑心中介騙來泰國打工嚼沿, 沒想到剛下飛機(jī)就差點兒被人妖公主榨干…… 1. 我叫王不留估盘,地道東北人。 一個月前我還...
    沈念sama閱讀 49,279評論 3 379
  • 正文 我出身青樓骡尽,卻偏偏與公主長得像遣妥,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子攀细,可洞房花燭夜當(dāng)晚...
    茶點故事閱讀 45,851評論 2 361