O que [[.ch.]] significa em um regex?

11

Título alternativo: o que é uma "sequência de agrupamento" ou "elemento de agrupamento" em um regex compatível com POSIX?

Eu encontrei a definição técnica exata em Seção 9.3.5 das especificações POSIX , como item # 4 na lista, mas não está muito claro para mim.

Eu pesquisei na web por exemplos e explicações e não cheguei completamente de mãos vazias, mas definitivamente não esclareceu .

A única coisa que tenho conseguido é que, em certas circunstâncias, você pode fazer seu regex tratar vários caracteres como se fossem um único caractere para fins de comparação de tamanho e determinar qual é a "correspondência mais longa" (desde regexes são gananciosos e retornam a partida mais longa possível).

Isso é tudo, embora? Estou com dificuldade em ver um uso para isso, mas suspeito que meu entendimento esteja incompleto. O que é realmente "agrupamento" para um regex? E como o [[.ch.]] , o exemplo nas especificações POSIX, se relaciona com isso?

    
por Wildcard 12.01.2016 / 10:36

2 respostas

7

Os elementos de agrupamento geralmente são referenciados no contexto da classificação.

Em muitos idiomas, o agrupamento (classificação como em um dicionário) não é feito apenas por caractere. Por exemplo, em tcheco, ch não classifica entre cg e ci como seria em inglês, mas é considerado como um todo para classificação. É um elemento de agrupamento (não podemos nos referir a um caractere aqui, o caractere é um subconjunto de elementos de agrupamento) que classifica entre h e i .

Agora você pode perguntar, O que isso tem a ver com expressões regulares? , Por que eu gostaria de me referir a um elemento de agrupamento em uma expressão de colchetes? .

Bem, dentro de expressões de colchetes, uma usa a ordem. Por exemplo, em [c-j] , você quer os caracteres entre c e j . Bem e você? Você prefere querer agrupar elementos lá. [h-i] em uma localidade checa corresponde a ch :

$ echo cho | LC_ALL=cs_CZ.UTF-8 grep '^[h-i]o'
cho

Portanto, se você conseguir listar vários elementos de agrupamento em uma expressão de colchetes, talvez espere poder listá-los individualmente também. [a-cch] corresponderia aos elementos de agrupamento entre a e c e os caracteres c e h . Para ter o a-c e o elemento de comparação ch , precisamos de uma nova sintaxe:

$ echo cho | LC_ALL=cs_CZ.UTF-8 grep '^[a-c[.ch.]]o'
cho

(aqueles entre a e c e ch um).

Agora, o mundo ainda não é perfeito e provavelmente nunca será. O exemplo acima estava em um sistema GNU e funcionou. Outro exemplo de um elemento collating poderia ser e com uma combinação de acento agudo em UTF-8 ( $'e\u0301' renderizado como $'\u00e9' as é ).

é e é o mesmo caractere , exceto que um é representado por um caractere e o outro por dois.

$ echo $'e\u301t\ue9' | grep '^[d-f]t'

Funcionará corretamente em alguns sistemas, mas não em outros (não no GNU, por exemplo). E não está claro se $'[[.\ue9.]]' deve corresponder apenas a $'\ue9' ou ambos $'\ue9' e $'e\u301' .

Sem mencionar scripts não alfabéticos, ou scripts com ordens de classificação diferentes, regionais, coisas como ffi ( ffi em um caractere) que se tornam complicadas de se lidar com uma API tão simples.

    
por 19.01.2016 / 13:08
1

Isso é útil quando caracteres não-ingleses (não-ascii) estão em uso. O exemplo ch que você mencionou é um dígrafo , ou seja, alguns idiomas têm uma letra em seu alfabeto que é / pode ser representado por duas letras em um alfabeto inglês.

Quando você usa [.ch.] em um regexp, basicamente diz: "Espero uma sequência de entrada que não seja em inglês com o dígrafo ch . Quero que meu regexp corresponda ao único caractere ch . Minha linguagem de programação / O motor / teclado regex não permite que eu escreva o sinal deste dígrafo, então eu digito [.ch.] . Não estou falando de c seguido de h . Por favor, encontre apenas ocorrências do dígrafo como um único caractere. "

[[.ch.]] significa que o dígrafo faz parte de um conjunto de caracteres. Neste caso, apenas um personagem, na verdade. Apenas a notação regexp padrão.

    
por 19.01.2016 / 12:29