Як зробити регулярний вираз, який не враховує регістр, у Go?


84

Тепер, звичайно, я міг би написати свій регулярний вираз для обробки обох випадків, наприклад regexp.Compile("[a-zA-Z]"), але мій регулярний вираз будується із рядка, заданого користувачем:

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

Де s.Nameце ім’я. Що може бути чимось на кшталт "Північ північним заходом". Зараз найбільш очевидним рішенням для мене було б пройти кожен символ s.Nameі написати '[nN]' для кожної літери:

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]))
  }
}

Але я вважаю, що це досить неелегантне рішення. Швидкість насправді не турбує, але мені потрібно знати, чи є інший спосіб.

Відповіді:


171

Ви можете встановити чутливий до регістру прапор як перший елемент у регулярному виразі.

Ви робите це, додаючи "(?i)"на початок регулярного виразу.

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

Для фіксованого регулярного виразу це буде виглядати так.

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

Щоб отримати докладнішу інформацію про прапори, знайдіть у regexp/syntaxдокументації пакета (або документації до синтаксису ) термін "прапори".


4
Але я виявив, що це занадто повільно, коли є багато даних. Через виклик unicode.SimpleFold у регулярному виразі.Match, тому я пропоную змінити літери на верхні, а потім використовувати регулярний вираз для відповідності. Це швидкість. Далі наведені дані про час: `` #By (? I) regexp to ignore case XCMP / bin / otacmp -o BSP_2.2.0.html -f BSP / framework -f Code / framework 1271.94s user 7.32s system 97% cpu 21: 54,95 # За верхнім та відповідністю XCMP / bin / otacmp -o BSP_2.2.0.html -f BSP / frameworks -f Код / фреймворки 263,87s користувач 8,99s система 110% cpu 4: 06,44 всього ``
QJGui

1
Схоже, повільна продуктивність нечутливого регулярного виразу була відомою помилкою, яку було виправлено у наступні місяці: github.com/golang/go/issues/13288
Ден Еспарза,

29

Ви можете додати a (?i)на початку шаблону, щоб зробити його чутливим до регістру.

Довідково



4

Використовуйте iпрапор. Цитування документації підказки :

Групування:

(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

Синтаксис прапора - xyz (встановити) або -xyz (очистити) або xy-z (встановити xy, очистити z). Прапори:

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)

22
Де в коді слід розмістити ці i, m, s та U?
Цянь Чень,

25
Ця відповідь така ж корисна, як і документація. На щастя, нижче є робочий приклад.
Лоран,
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.