Как сделать в Go регулярное выражение без учета регистра?


85

Теперь, конечно, я мог бы написать свое регулярное выражение для обработки обоих случаев, например 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 в regexp.Match, поэтому я предлагаю изменить буквы на верхние, а затем использовать регулярное выражение для сопоставления. Это скорость. Ниже приведены данные о времени: `` #By (? I) regexp, чтобы игнорировать регистр XCMP / bin / otacmp -o BSP_2.2.0.html -f BSP / frameworks -f Код / frameworks 1271.94s user 7.32s system 97% cpu 21: 54.95 всего # By toUpper и сопоставьте XCMP / bin / otacmp -o BSP_2.2.0.html -f BSP / frameworks -f Code / frameworks 263.87s user 8.99s system 110% cpu 4: 06.44 total ''
QJGui

1
Похоже, низкая производительность для регулярных выражений без учета регистра была известной ошибкой, которая была исправлена ​​в следующие месяцы: github.com/golang/go/issues/13288
Дэн Эспарза

29

Вы можете добавить (?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)

23
Где в коде я должен поместить эти i, m, s и U?
Цянь Чен

26
Этот ответ так же бесполезен, как и документация. К счастью, ниже есть рабочий пример.
Laurent
Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.