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

Я видел много примеров создания целого регулярного выражения без учета регистра. Что меня интересует, так это то, что только часть выражения нечувствительна к регистру.

Например, допустим, у меня есть такая строка:

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 означает, что он не захватывает, а просто используется для группировки терминов | (или) заявление.

Другие вопросы по тегам