Você pode fazer com que apenas parte de uma regex não faça distinção entre maiúsculas e minúsculas?

100

Já vi muitos exemplos de como tornar uma expressão regular inteira sem distinção entre maiúsculas e minúsculas. O que estou pensando é que apenas parte da expressão não faz distinção entre maiúsculas e minúsculas.

Por exemplo, digamos que eu tenha uma string como esta:

fooFOOfOoFoOBARBARbarbarbAr

E se eu quiser fazer a correspondência de todas as ocorrências de "foo", independentemente da caixa, mas só quiser corresponder as "BAR" maiúsculas?

A solução ideal seria algo que funcionasse em todos os tipos de regex, mas também estou interessado em ouvir aqueles específicos de linguagem (Obrigado, Espo )

Editar

O link fornecido pelo Espo foi muito útil. Há um bom exemplo sobre como ativar e desativar modificadores na expressão.

Para meu exemplo inventado, posso fazer algo assim:

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

o que torna a correspondência insensível a maiúsculas e minúsculas apenas para a parte foo da correspondência.

Isso pareceu funcionar na maioria das implementações de regex, exceto Javascript, Python e alguns outros (como o Espo mencionou).

Todos os grandes sobre os quais eu estava pensando (Perl, PHP, .NET) oferecem suporte a alterações de modo embutido.

Mark Biek
fonte
Esta pergunta foi adicionada às Perguntas frequentes sobre expressões regulares do Stack Overflow , em "Modificadores".
aliteralmind de

Respostas:

88

Perl permite que você torne parte da sua expressão regular não sensível a maiúsculas e minúsculas usando o modificador de padrão (? I :).

Os sabores de regex modernos permitem que você aplique modificadores a apenas parte da expressão regular. Se você inserir o modificador (? Ism) no meio da regex, o modificador só se aplica à parte da regex à direita do modificador. Você pode desligar os modos precedendo-os com um sinal de menos. Todos os modos após o sinal de menos serão desligados. Por exemplo, (? I-sm) ativa a insensibilidade a maiúsculas e minúsculas e desativa o modo de linha única e o modo de linha múltipla.

Nem todos os sabores de regex suportam isso. JavaScript e Python aplicam todos os modificadores de modo a toda a expressão regular. Eles não suportam a sintaxe (? -Ismx), visto que desligar uma opção é inútil quando os modificadores de modo se aplicam a todas as expressões regulares. Todas as opções estão desativadas por padrão.

Você pode testar rapidamente como o tipo de regex que está usando controla os modificadores de modo. A regex (? I) te (? - i) st deve corresponder a test e TEst, mas não a teST ou TEST.

Fonte

Espo
fonte
6

Que linguagem você está usando? Uma maneira padrão de fazer isso seria algo como / ([Ff] [Oo] {2} | BAR) / com diferenciação de maiúsculas e minúsculas, mas em Java, por exemplo, há um modificador de diferenciação de maiúsculas e minúsculas (? I) que torna tudo caracteres à direita insensíveis a maiúsculas e minúsculas e (? -i) que força a sensibilidade. Um exemplo desse modificador regex Java pode ser encontrado aqui .

Akdom
fonte
+1 Por que se preocupar em não
diferenciar
11
@NonaUrbiz: Porque a expressão (?i)foobaré mais legível do que[Ff][Oo]{2}[Bb][Aa][Rr]
Thanatos,
1
E porque ele pode crescer maneira muito mais peludo e complexa.
Corte de
6

Infelizmente, a sintaxe para correspondência sem distinção entre maiúsculas e minúsculas não é comum. No .NET, você pode usar a sinalização RegexOptions.IgnoreCase ou o modificador ? I

aku
fonte
4

Você poderia usar

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

O?: Entre colchetes em .Net significa que não está capturando e é usado apenas para agrupar os termos do | (ou) declaração.

Kibee
fonte
26
Não é "[fF] [oO] [oO]" a melhor alternativa? Para o exemplo em questão, você poderia ir tão longe quanto "[fF] [oO] \ {2}" ;-)
Tomalak
4

É verdade que se pode confiar nos modificadores embutidos, conforme descrito em Ativando e desativando os modos apenas para parte da expressão regular :

A regex (?i)te(?-i)stdeve corresponder a teste e TEst, mas não a teSTou TEST.

No entanto, um recurso um pouco mais suportado é um (?i:...)grupo de modificadores embutidos (consulte Modifier Spans ). A sintaxe é (?i:, então o padrão que você deseja tornar não sensível a cas e, em seguida, a ).

(?i:foo)|BAR

O inverso : Se o seu padrão é compilado com a opção insensível caso e você precisa fazer uma parte de um caso regex sensível, você adicionar -depois ?: (?-i:...).

Exemplo de uso em vários idiomas (envolvendo as correspondências com colchetes angulares):

  • - preg_replace("~(?i:foo)|BAR~", '<$0>', "fooFOOfOoFoOBARBARbarbarbAr")( demonstração )
  • - re.sub(r'(?i:foo)|BAR', r'<\g<0>>', 'fooFOOfOoFoOBARBARbarbarbAr')( demonstração ) (observe que o Python reoferece suporte a grupos modificadores embutidos desde o Python 3.6)
  • / / - Regex.Replace("fooFOOfOoFoOBARBARbarbarbAr", "(?i:foo)|BAR", "<$&>")( demonstração )
  • - "fooFOOfOoFoOBARBARbarbarbAr".replaceAll("(?i:foo)|BAR", "<$0>")( demonstração )
  • - $s =~ s/(?i:foo)|BAR/<$&>/g( demonstração )
  • - "fooFOOfOoFoOBARBARbarbarbAr".gsub(/(?i:foo)|BAR/, '<\0>')( demonstração )
  • - gsub("((?i:foo)|BAR)", "<\\1>", "fooFOOfOoFoOBARBARbarbarbAr", perl=TRUE)( demonstração )
  • - "fooFOOfOoFoOBARBARbarbarbAr".replacingOccurrences(of: "(?i:foo)|BAR", with: "<$0>", options: [.regularExpression])
  • - (usa RE2) - regexp.MustCompile(`(?i:foo)|BAR`).ReplaceAllString( "fooFOOfOoFoOBARBARbarbarbAr", `<${0}>`)( demonstração )

Não suportado em , , , std::regex, , .

Wiktor Stribiżew
fonte