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

102

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

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

fooFOOfOoFoOBARBARbarbarbAr

Что, если я хочу сопоставить все вхождения «foo» независимо от регистра, но хочу сопоставить только «BAR» в верхнем регистре?

Идеальным решением было бы что-то, что работает с различными вариантами регулярных выражений, но я также заинтересован в том, чтобы услышать специфические для языка (спасибо Espo )

редактировать

Ссылка, предоставленная Эспо, была очень полезной. Там есть хороший пример включения и выключения модификаторов внутри выражения.

В моем надуманном примере я могу сделать что-то вроде этого:

(?i)foo*(?-i)|BAR

что делает совпадение нечувствительным к регистру только для части совпадения foo.

Казалось, что это работает в большинстве реализаций регулярных выражений, кроме Javascript, Python и некоторых других (как упоминал Эспо).

Все большие, о которых мне было интересно (Perl, PHP, .NET), поддерживают изменения встроенного режима.

Марк Бик
источник
Этот вопрос был добавлен в FAQ по регулярным выражениям при переполнении стека в разделе «Модификаторы».
aliteralmind

Ответы:

88

Perl позволяет сделать часть вашего регулярного выражения нечувствительной к регистру с помощью модификатора шаблона (? I :).

Современные разновидности регулярных выражений позволяют применять модификаторы только к части регулярного выражения. Если вы вставите модификатор (? Ism) в середину регулярного выражения, модификатор применяется только к той части регулярного выражения, которая находится справа от модификатора. Вы можете выключить режимы, поставив перед ними знак минус. Все режимы после знака минус будут отключены. Например, (? I-sm) включает нечувствительность к регистру и выключает как однострочный, так и многострочный режим.

Не все разновидности регулярных выражений поддерживают это. JavaScript и Python применяют все модификаторы режима ко всему регулярному выражению. Они не поддерживают синтаксис (? -Ismx), так как отключение опции бессмысленно, когда модификаторы режима применяются ко всем регулярным выражениям. По умолчанию все параметры отключены.

Вы можете быстро проверить, как используемый вами вариант регулярного выражения обрабатывает модификаторы режима. Регулярное выражение (? I) te (? - i) st должно соответствовать test и TEst, но не teST или TEST.

Источник

Espo
источник
6

На каком языке ты говоришь? Стандартный способ сделать это - что-то вроде / ([Ff] [Oo] {2} | BAR) / с включенной чувствительностью к регистру, но в Java, например, есть модификатор чувствительности к регистру (? I), который делает все символы справа от него нечувствительны к регистру и (? -i), который устанавливает чувствительность. Пример этого модификатора регулярного выражения Java можно найти здесь .

акдом
источник
+1 Зачем делать регистр нечувствительным, если можно сопоставить оба случая
Нона Урбиз
11
@NonaUrbiz: Потому что это выражение (?i)foobarболее читабельно, чем[Ff][Oo]{2}[Bb][Aa][Rr]
Танатос
1
И потому , что она может расти путь гораздо более волосатые и сложным.
Чоп
6

К сожалению, синтаксис для сопоставления без учета регистра встречается нечасто. В .NET вы можете использовать флаг RegexOptions.IgnoreCase или модификатор ? I

аку
источник
5

Это правда, что можно полагаться на встроенные модификаторы, как описано в разделе Включение и выключение режимов только для части регулярного выражения :

Регулярное выражение (?i)te(?-i)stдолжно соответствовать test and TEst, но не teSTor TEST.

Однако немного более поддерживаемая функция - это (?i:...)встроенная группа модификаторов (см. Диапазон модификаторов ). Синтаксис (?i:, затем шаблон, который вы хотите сделать нечувствительным к случайному совпадению, а затем файл ).

(?i:foo)|BAR

Реверс : Если ваш шаблон скомпилирован с опцией без учета регистра , и вы должны сделать часть случая регулярных выражений чувствительна, вы добавляете -после ?: (?-i:...).

Пример использования на разных языках (заключение совпадений в угловые скобки):

  • - preg_replace("~(?i:foo)|BAR~", '<$0>', "fooFOOfOoFoOBARBARbarbarbAr")( демо )
  • - re.sub(r'(?i:foo)|BAR', r'<\g<0>>', 'fooFOOfOoFoOBARBARbarbarbAr')( демонстрация ) (обратите внимание, что Python reподдерживает встроенные группы модификаторов, начиная с Python 3.6)
  • / / - Regex.Replace("fooFOOfOoFoOBARBARbarbarbAr", "(?i:foo)|BAR", "<$&>")( демо )
  • - "fooFOOfOoFoOBARBARbarbarbAr".replaceAll("(?i:foo)|BAR", "<$0>")( демо )
  • - $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])
  • - (использует RE2) - regexp.MustCompile(`(?i:foo)|BAR`).ReplaceAllString( "fooFOOfOoFoOBARBARbarbarbAr", `<${0}>`)( демо )

Не поддерживается в , , , std::regex, , .

Виктор Стрибьев
источник
4

Вы могли бы использовать

(?:F|f)(?:O|o)(?:O|o)

Знак?: В скобках в .Net означает, что он не захватывает, и просто используется для группировки терминов | (или) заявление.

Кибби
источник
26
Разве "[fF] [oO] [oO]" не лучшая альтернатива? В данном примере вы можете даже пойти так далеко, как "[fF] [oO] \ {2}" ;-)
Tomalak