Регулярни изрази
18.11.2013
pattern matching
през 1962г.ed
, sed
, grep
, egrep
, awk
, and lex
...най-общо: работа с текстови низове
Искаме да проверим дали даден низ е валиден мобилен номер.
Това означава:
func isValidMobilePhone(number string) bool { code := number[:3] if code != "087" && code != "088" && code != "089" { return false } if number[3] == '0' || number[3] == '1' { return false } return len(number[4:]) == 6 }
func isValidMobilePhone(number string) bool { return regexp.MustCompile(`^08[789][2-9]\d{6}$`).MatchString(number) }
Nice, a?
regexp
regexp.Regexp
Find(All)?(String)?(Submatch)?(Index)?
godoc regexp/syntax
Всеки символ, освен някои специални, означава себе си.
Цялата магия е в специалните символи:
. \| ( ) [ ] { } + \ ^ $ * ?
Някои символи са специални само в определен контекст (например символът -)
Compile()
или MustCompile()
re, err := regexp.Compile(`Hello`) re := regexp.MustCompile(`Hello`)
Второто изпада в паника, ако регулярният израз не е валиден
re := regexp.MustCompile(`Hello`) if re.MatchString("Hello Regular Expression.") { fmt.Printf("Match ") } else { fmt.Printf("No match ") }
matcher(`pat`, "Find a pattern.") // Find a (pat)tern. matcher(`#`, "What the ###?") // What the (#)##?
В последното можем да пропуснем m или n:
matcher(`pat`, "Find a pattern.") // Find a (pat)tern. matcher(`#`, "What the ###?") // What the (#)##?
?
след квантора.*?
кара повторителя *
да се държи не-лакомоmatcher(`[hH]o+`, "Hoooooohohooo...") // (Hoooooo)hohooo... matcher(`[hH]o+?`, "Hoooooohohooo...") // (Ho)ooooohohooo...
matcher(`o+`, "Goooooooogle") // G(oooooooo)gle matcher(`[hH]o+`, "Hohohoho...") // (Ho)hohoho...
Хм. Не искахме точно това. По-скоро:
matcher(`([hH]o)+`, "Hohohoho...") // (Hohohoho)... matcher(`([hH]o){2,3}`, "Hohohoho...") // (Hohoho)ho...
Символите (
и )
се използват за логическо групиране на части от шаблона с цел:
Повече за тях -- след малко
Символът |
има смисъла на "или"
matcher(`day|nice`, "A nice dance-day.") // A (nice) dance-day. matcher(`da(y|n)ce`, "A nice dance-day.") // A nice (dance)-day.
NB! Единствено |
се прилага не над непосредствените му
символи/класове, а на целия низ отляво/отдясно:
matcher(`ab|c|e`, "abcdef") // (ab)cdef matcher(`am|c|e`, "abcdef") // ab(c)def matcher(`a(m)|c|e`, "abcdef") // ab(c)def
Набор от символи, заграден от [
и ]
, например [aeoui]
.
Съвпадат с точно един от символите, описани в класа:
matcher(`[aeoui]`, "Google") // G(o)ogle
Отрицание на символен клас -- ^
в началото на класа:
matcher(`[^CBL][aeoui]`, "Cobol") // 'Co(bo)l'
Диапазон от символи -- -
между два символа в символен клас:
matcher(`[0-9]{1,3}-[a-z]`, "Figure 42-b") // Figure (42-b) matcher(`[^a-zA-Z-]`, "Figure-42-b") // Figure-(4)2-b
Символите ( и ) се използват за логическо групиране на части от шаблона с цел:
\bda(y|nce)\b
re := regexp.MustCompile(`.at`) res := re.FindAllStringSubmatch("The cat sat on the mat.", -1) fmt.Printf("%v", res) // [[cat] [sat] [mat]]
Можем да разменим местата на две думи
re := regexp.MustCompile("([a-z]+) ([a-z]+)") re.ReplaceAllString("foo bar", "$2 $1")
или да имаме по-сложна логикa, върху всяко от съвпаденията
re.ReplaceAllStringFunc("foo with bar", func(match string) string { if len(match) > 3 { return match + "!!!" } return match }) // foo with!!! bar
или ...
re := regexp.MustCompile("a(x*)b") fmt.Println(re.ReplaceAllLiteralString("-ab-axxb-", "Щ")) // -Щ-Щ-
Обяснете последното :)
Често strings.Split()
е крайно недостатъчен.
re := regexp.MustCompile("[0-9]") re.Split("Помощ1не2ми3работи4space5клавиша!", -1) // []string{"Помощ" "не" "ми" "работи" "space" "клавиша!"}
Вторият аргумент указва максималната дължина на върнатия слайс.
re := regexp.MustCompile("[0-9]") re.Split("Помощ1не2ми3работи4space5клавиша!", 3) // []string{"Помощ" "не" "ми3работи4space5клавиша!"}
regexp.Compile(`(?i)n`)
func matcher(pattern, text string) string { match := regexp.MustCompile(pattern).FindStringIndex(text) if match == nil { return "" } begin := match[0] end := match[1] return fmt.Sprintf("%s(%s)%s\n", text[:begin], text[begin:end], text[end:]) }
Encouraging regular expressions as a panacea for all text processing
problems is not only lazy and poor engineering, it also reinforces
their use by people who shouldn't be using them at all.
-- Rob Pike
commandcenter.blogspot.ch/2011/08/regular-expressions-in-lexing-and.html
but is slow in Java, Perl, PHP, Python, Ruby, ...
Russ Cox
rsc@swtch.com
January 2007