Can you make just part of a regex case-insensitive?

I've seen lots of examples of making an entire regular expression case-insensitive. What I'm wondering about is having just part of the expression be case-insensitive.

For example, let's say I have a string like this:

fooFOOfOoFoOBARBARbarbarbAr

What if I want to match all occurrences of "foo" regardless of case but I only want to match the upper-case "BAR"s?

The ideal solution would be something that works across regex flavors but I'm interested in hearing language-specific ones as well (Thanks Espo)

Edit

The link Espo provided was very helpful. There's a good example in there about turning modifiers on and off within the expression.

For my contrived example, I can do something like this:

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

which makes the match case-insensitive for just the foo portion of the match.

That seemed to work in most regex implementations except Javascript, Python, and a few others (as Espo mentioned).

The big ones that I was wondering about (Perl, PHP, .NET) all support inline mode changes.

91268 次浏览

Perl 允许您使用(? i:)模式修饰符使正则表达式的一部分不区分大小写。

现代的正则表达式风格允许您仅对正则表达式的一部分应用修饰符。如果您插入修饰符(?Ism) ,修饰符只应用于修饰符右边的部分。可以通过在模式前面加上一个减号来关闭模式。负号后的所有模式将被关闭。例如(?I-sm)开启不区分大小写,同时关闭单线模式和多线模式。

并非所有的正则表达式都支持这一点。JavaScript 和 Python 将所有模式修饰符应用于整个正则表达式。他们不支持(?- ismx)语法,因为当模式修饰符应用于整个正则表达式时,关闭选项是没有意义的。默认情况下,所有选项都是关闭的。

您可以快速测试您正在使用的正则表达式风格如何处理模式修饰符。正则表达式(?(德语)?I) st 应匹配 TEst 和 TEst,但不匹配 TEst 或 TEST。

Source

你可以用

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

什么?: 在括号内。Net 意味着它是非捕获的,并且只用于对 | (或)语句的术语进行分组。

你用什么语言?一个标准的方法是像/([ Ff ][ Oo ]{2} | bAR)/这样打开大小写敏感性,但是在 Java 中,例如,有一个大小写敏感性修饰符(?I)这使得它右边的所有字符都不区分大小写,并且(?- i)迫使敏感性。这个 Javaregex 修饰符的一个示例可以在 给你中找到。

不幸的是,不区分大小写的匹配语法并不常见。 在.NET 中,可以使用 RegexOptions.IgnoreCase 标志或 修饰符

的确,我们可以依赖于 只为正则表达式的一部分打开和关闭模式中描述的内联修饰符:

正则表达式 (?i)te(?-i)st应该匹配 test 和 TEst,但不匹配 teSTTEST

但是,更受支持的特性是 内联修饰词组(参见 < em > 修饰符跨度 )。语法是 (?i:,然后是您希望不区分大小写的模式,然后是 )

(?i:foo)|BAR

反向 : 如果您的模式是使用不区分大小写的选项编译的,并且您需要使正则表达式的一部分区分大小写,那么您可以在 ?: (?-i:...)之后添加 -

各种语言中的示例用法(用尖括号包装匹配项) :

  • -preg_replace("~(?i:foo)|BAR~", '<$0>', "fooFOOfOoFoOBARBARbarbarbAr")(小样)
  • -re.sub(r'(?i:foo)|BAR', r'<\g<0>>', 'fooFOOfOoFoOBARBARbarbarbAr')(小样)(注意自 Python 3.6以来的 Python re支持内联修饰符组)
  • //-Regex.Replace("fooFOOfOoFoOBARBARbarbarbAr", "(?i:foo)|BAR", "<$&>")(小样)
  • -"fooFOOfOoFoOBARBARbarbarbAr".replaceAll("(?i:foo)|BAR", "<$0>")(demo)
  • -$s =~ s/(?i:foo)|BAR/<$&>/g(demo)
  • -"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中不支持。

在这种情况下,您可以将两个字母变体放入一个字符类(不是一个组,参见 为什么一个字符类比交替更快?):

  • -sed -E 's/[Ff][Oo][Oo]|BAR/<&>/g' file > outfile(小样)
  • -grep -Eo '[Ff][Oo][Oo]|BAR' file(或者如果使用 GNU grep,仍然可以使用 PCRE regex,grep -Po '(?i:foo)|BAR' file(小样))