Jak zrobić wyrażenie regularne bez rozróżniania wielkości liter w Go?

84

Teraz, oczywiście, mógłbym napisać moje wyrażenie regularne, aby obsłużyć oba przypadki, na przykład regexp.Compile("[a-zA-Z]"), ale moje wyrażenie regularne jest zbudowane z ciągu podanego przez użytkownika:

reg, err := regexp.Compile(strings.Replace(s.Name, " ", "[ \\._-]", -1))

Gdzie s.Namejest nazwa. Może to być coś w rodzaju „North by Northwest”. Teraz najbardziej oczywistym rozwiązaniem byłoby dla mnie przejście przez każdy znak s.Namei napisanie „[nN]” dla każdej litery:

for i := 0; i < len(s.Name); i++ {
  if s.Name[i] == " " {
    fmt.Fprintf(str, "%s[ \\._-]", str);
  } else {
    fmt.Fprintf(str, "%s[%s%s]", str, strings.ToLower(s.Name[i]), strings.ToUpper(s.Name[i]))
  }
}

Ale wydaje mi się, że to raczej mało eleganckie rozwiązanie. Szybkość nie jest tak naprawdę problemem, ale muszę wiedzieć, czy jest inny sposób.

Svip
źródło

Odpowiedzi:

171

Możesz ustawić flagę bez rozróżniania wielkości liter jako pierwszy element w wyrażeniu regularnym.

Robisz to, dodając "(?i)"na początku wyrażenia regularnego.

reg, err := regexp.Compile("(?i)"+strings.Replace(s.Name, " ", "[ \\._-]", -1))

W przypadku stałego wyrażenia regularnego wyglądałoby to tak.

r := regexp.MustCompile(`(?i)CaSe`)

Aby uzyskać więcej informacji o flagach, poszukaj w regexp/syntaxdokumentacji pakietu (lub dokumentacji składni ) terminu „flagi”.

Daniel
źródło
4
Ale okazało się, że jest to zbyt wolne, gdy jest wiele danych. Ze względu na wywołanie unicode.SimpleFold w regexp.Match, sugeruję zmianę liter na wielkie, a następnie użycie wyrażenia regularnego w celu dopasowania. To jest prędkość. Poniżej znajdują się dane dotyczące czasu: `` #By (? I) wyrażenie regularne, aby zignorować wielkość liter XCMP / bin / otacmp -o BSP_2.2.0.html -f BSP / frameworks -f Kod / frameworki 1271,94s użytkownik 7,32s system 97% cpu 21: 54,95 łącznie #By toUpper and match XCMP / bin / otacmp -o BSP_2.2.0.html -f BSP / frameworks -f Kod / frameworki 263,87s użytkownik 8,99s system 110% cpu 4: 06,44 łącznie ``
QJGui
1
Wygląda na to, że powolne działanie w przypadku wyrażenia regularnego bez
Dan Esparza
29

Możesz dodać (?i)na początku wzoru, aby wielkość liter nie była rozróżniana.

Odniesienie

Qtax
źródło
4

Użyj iflagi. Cytując dokumentację porad :

Grupowanie:

(re)           numbered capturing group
(?P<name>re)   named & numbered capturing group
(?:re)         non-capturing group
(?flags)       set flags within current group; non-capturing
(?flags:re)    set flags during re; non-capturing

Składnia flagi to xyz (zestaw) lub -xyz (wyczyść) lub xy-z (zestaw xy, wyczyść z). Flagi to:

i              case-insensitive (default false)
m              multi-line mode: ^ and $ match begin/end line in addition to begin/end text (default false)
s              let . match \n (default false)
U              ungreedy: swap meaning of x* and x*?, x+ and x+?, etc (default false)
zzzz
źródło
22
Gdzie w kodzie mam umieścić te I, M, S i U?
Qian Chen
25
Ta odpowiedź jest równie nieprzydatna, jak dokumentacja. Na szczęście poniżej znajduje się działający przykład.
laurent