Estou usando o bash no Linux. Estou obtendo sucesso com a seguinte instrução if, mas isso não deve retornar um código de falha?
if [[ ■ = [⅕⅖⅗] ]] ; then echo yes ; fi
O quadrado NÃO é igual a nenhum dos caracteres, portanto não vejo por que recebo um código de sucesso.
É importante para mim manter os colchetes duplos no meu caso.
Existe alguma outra maneira de fazer um intervalo nesse cenário ou outras sugestões?
C
não funcionará aqui, pois não são caracteres de byte único.C.UTF-8
faria quando disponível.Respostas:
Isso é uma conseqüência desses caracteres terem a mesma ordem de classificação.
Você também notará que
retorna apenas uma linha.
Ou aquilo:
retorna true (conforme exigido pelo POSIX).
A maioria das localidades fornecidas com os sistemas GNU possui um número de caracteres (e até sequências de caracteres (sequências de intercalação)) que têm a mesma ordem de classificação. No caso desses, é porque a ordem não está definida e os caracteres cuja ordem não está definida acabam tendo a mesma ordem de classificação nos sistemas GNU. Existem caracteres definidos explicitamente como tendo a mesma ordem de classificação como Ș e Ş (embora não exista (para mim, de qualquer maneira) lógica ou consistência reais de como isso é feito).
Essa é a fonte de comportamentos bastante surpreendentes e falsos. Eu levantei a questão muito recentemente na lista de discussão do grupo Austin (o corpo por trás do POSIX e da Especificação Única UNIX) e a discussão ainda está em andamento a partir de 03/04/2015.
Nesse caso, se
[y]
devo combinarx
ondex
ey
classificar o mesmo não está claro para mim, mas como uma expressão de colchete deve corresponder a um elemento de intercalação, isso sugere que obash
comportamento é esperado.Em qualquer caso, suponho
[⅕-⅕]
ou pelo menos[⅕-⅖]
devo corresponder■
.Você notará que ferramentas diferentes se comportam de maneira diferente. O ksh93 se comporta como
bash
, GNUgrep
oused
não. Algumas outras conchas têm comportamentos diferentes, algumas comoyash
buggy ainda mais.Para ter um comportamento consistente, você precisa de uma localidade em que todos os caracteres sejam classificados de maneira diferente. O código de idioma C é o típico. No entanto, o conjunto de caracteres no código de idioma C na maioria dos sistemas é ASCII. Nos sistemas GNU, você geralmente tem acesso a um
C.UTF-8
código do idioma que pode ser usado para trabalhar com caracteres UTF-8.Tão:
ou o equivalente-padrão:
deve retornar false.
Outra alternativa seria definir apenas
LC_COLLATE
C que funcionaria em sistemas GNU, mas não necessariamente em outras onde poderia falhar em especificar a ordem de classificação do caractere de vários bytes.Uma lição disso é que igualdade não é uma noção tão clara quanto seria de esperar quando se trata de comparar strings. Igualdade pode significar, do mais estrito ao menos estrito.
Agora, para 2 ou 3, isso pressupõe que ambas as cadeias contêm caracteres válidos. No UTF-8 e em algumas outras codificações, alguma sequência de bytes não forma caracteres válidos.
1 e 2 não são necessariamente equivalentes por causa disso ou porque alguns caracteres podem ter mais de uma codificação possível. Esse é geralmente o caso de codificações com estado, como ISO-2022-JP, onde
A
podem ser expressas como41
ou1b 28 42 41
(1b 28 42
sendo a sequência para alternar para ASCII e você pode inserir quantas delas quiser, que não farão diferença), embora eu não esperaria que esses tipos de codificação ainda estivessem em uso, e as ferramentas GNU pelo menos geralmente não funcionam corretamente com elas.Lembre-se também de que a maioria dos utilitários não-GNU não pode lidar com o valor de 0 byte (o caractere NUL em ASCII).
Qual dessas definições é usada depende do utilitário e da implementação ou versão do utilitário. O POSIX não é 100% claro nisso. No código C, todos os 3 são equivalentes. Fora desse YMMV.
fonte
é
eé
ser a mesma string, mas nãoe
. A noção de ordem de agrupamento do POSIX raramente é correta, é muito baseada em caracteres e não é responsável pelas formas mais comuns de classificar seqüências de caracteres (por exemplo, dicionários franceses não usam uma ordem lexicográfica para classificar palavras: eles fazem uma primeira passagem lexicográfica com acentos ignorados e use acentos para decidir laços).Você está fazendo errado,
=
e==
não é o mesmo.Experimente estes exemplos:
fonte
=
deve ser usado para verificar a igualdade. O problema são as cotações ausentes, não o operador.man bash
diz na[[
seção: "O operador = é equivalente a ==."[[...]]
operador. E = e == são os mesmos nos shells em que foram implementados (ksh / bash / zsh) e para correspondência de padrões, não igualdade.