Можете ли вы сделать только часть регулярного выражения без учета регистра?
Я видел много примеров создания целого регулярного выражения без учета регистра. Что меня интересует, так это то, что только часть выражения нечувствительна к регистру.
Например, допустим, у меня есть такая строка:
fooFOOfOoFoOBARBARbarbarbAr
Что если я хочу сопоставить все вхождения "foo" независимо от регистра, но я хочу сопоставить только прописные буквы "BAR"?
Идеальным решением было бы то, что работает с различными типами регулярных выражений, но я также заинтересован в том, чтобы услышать и языковые (спасибо Espo)
редактировать
Ссылка, предоставленная Espo, была очень полезной. Там есть хороший пример включения и выключения модификаторов в выражении.
Для моего надуманного примера я могу сделать что-то вроде этого:
(?i)foo*(?-i)|BAR
что делает совпадение без учета регистра только для части foo совпадения.
Похоже, это работает в большинстве реализаций регулярных выражений, кроме Javascript, Python и некоторых других (как упоминал Эспо).
Большие из них, о которых мне было интересно (Perl, PHP, .NET), поддерживают изменения в встроенном режиме.
4 ответа
Perl позволяет сделать часть вашего регулярного выражения без учета регистра с помощью модификатора шаблона (? I:).
Современные регулярные выражения позволяют применять модификаторы только к части регулярного выражения. Если вы вставите модификатор (? Ism) в середину регулярного выражения, модификатор применяется только к части регулярного выражения справа от модификатора. Вы можете отключить режимы, поставив перед ними знак минус. Все режимы после знака минус будут отключены. Например, (? I-sm) включает нечувствительность к регистру и отключает как однострочный, так и многострочный режим.
Не все регулярные выражения поддерживают это. JavaScript и Python применяют все модификаторы режима ко всему регулярному выражению. Они не поддерживают синтаксис (?-Ismx), поскольку отключение параметра не имеет смысла, когда модификаторы режима применяются ко всем регулярным выражениям. Все параметры по умолчанию отключены.
Вы можете быстро проверить, как с помощью регулярных выражений вы используете модификаторы режима. Регулярное выражение (? I)te(?-i)st должно соответствовать test и TEst, но не teST или TEST.
Это правда, что можно полагаться на встроенные модификаторы, как описано в разделе Включение и выключение режимов только для части регулярного выражения:
Регулярное выражение
(?i)te(?-i)st
должен соответствовать тесту иTEst
, но нетteST
илиTEST
.
Однако немного более поддерживаемая функция - это (?i:...)
встроенная группа модификаторов (см. Диапазон модификаторов). Синтаксис(?i:
, затем шаблон, который вы хотите сделать без учета случайной чувствительности, а затем )
.
(?i:foo)|BAR
Обратное: если ваш шаблон скомпилирован с параметром без учета регистра и вам нужно сделать часть регулярного выражения чувствительной к регистру, вы добавляете-
после ?
: (?-i:...)
.
Пример использования на разных языках (заключение совпадений в угловые скобки):
- php -
preg_replace("~(?i:foo)|BAR~", '<$0>', "fooFOOfOoFoOBARBARbarbarbAr")
(демо) - питон -
re.sub(r'(?i:foo)|BAR', r'<\g<0>>', 'fooFOOfOoFoOBARBARbarbarbAr')
(демонстрация) (обратите внимание на Pythonre
поддерживает встроенные группы модификаторов, начиная с Python 3.6) - С # / vb.net / .net -
Regex.Replace("fooFOOfOoFoOBARBARbarbarbAr", "(?i:foo)|BAR", "<$&>")
(демо) - java -
"fooFOOfOoFoOBARBARbarbarbAr".replaceAll("(?i:foo)|BAR", "<$0>")
(демо) - perl -
$s =~ s/(?i:foo)|BAR/<$&>/g
(демо) - рубин -
"fooFOOfOoFoOBARBARbarbarbAr".gsub(/(?i:foo)|BAR/, '<\0>')
(демо) - г -
gsub("((?i:foo)|BAR)", "<\\1>", "fooFOOfOoFoOBARBARbarbarbAr", perl=TRUE)
(демо) - быстро -
"fooFOOfOoFoOBARBARbarbarbAr".replacingOccurrences(of: "(?i:foo)|BAR", with: "<$0>", options: [.regularExpression])
- go - (использует RE2) -
regexp.MustCompile(`(?i:foo)|BAR`).ReplaceAllString( "fooFOOfOoFoOBARBARbarbarbAr", `<${0}>`)
(демо)
Не поддерживается в javascript, bash, sed, C++ std::regex
, lua, tcl.
К сожалению, синтаксис сопоставления без учета регистра не распространен. В.NET вы можете использовать флаг RegexOptions.IgnoreCase или модификатор ? I
Какой язык вы используете? Стандартный способ сделать это - что-то вроде /([Ff][Oo]{2}|BAR)/ с включенной чувствительностью к регистру, но в Java, например, есть модификатор чувствительности к регистру (? I), который делает все символы справа от него не чувствительны к регистру и (?-i), который вызывает чувствительность. Пример этого модификатора Java regex можно найти здесь.
Вы могли бы использовать
(?:F|f)(?:O|o)(?:O|o)
Символ?: В скобках.Net означает, что он не захватывает, а просто используется для группировки терминов | (или) заявление.