[A-Z]
in bash
corresponde a todos os elementos de intercalação (caracteres, mas também podem ser sequências de caracteres, como Dsz
nas localidades húngaras) que são classificadas após A
e classificadas antes Z
. No seu local, c
provavelmente classifica entre B e C.
$ printf '%s\n' A a á b B c C Ç z Z Ẑ | sort
a
A
á
b
B
c
C
Ç
z
Z
Ẑ
Então, c
ou z
seria correspondido por [A-Z]
, mas não Ẑ
ou a
.
$ printf '%s\n' A a á b B c C Ç z Z Ẑ |
pipe> bash -c 'while IFS= read -r x; do case $x in [A-Z]) echo "$x"; esac; done'
A
á
b
B
c
C
Ç
z
Z
No código C, o pedido seria:
$ printf '%s\n' A a á b B c C Ç z Z Ẑ | LC_COLLATE=C sort
A
B
C
Z
a
b
c
z
Ç
á
Ẑ
Então [A-Z]
iria corresponder A
, B
, C
, Z
, mas não Ç
e ainda não Ẑ
.
Se você deseja combinar com letras maiúsculas (em qualquer script), você pode usá-lo [[:upper:]]
. Não existe uma maneira incorporada bash
de combinar apenas letras maiúsculas no script latino (exceto listando-as individualmente).
Se você quiser combinar com o A
de Z
Inglês letras sem diacríticos, você pode usar [A-Z]
ou [[:upper:]]
mas no C
local (assumindo que os dados não são codificados em conjuntos de caracteres como BIG5 ou GB18030, que tem vários personagens cujas codificação contém a codificação dessas cartas) ou lista eles individualmente ( [ABCDEFGHIJKLMNOPQRSTUVWXYZ]
).
Observe que há alguma variação entre as conchas.
For zsh
, bash -O globasciiranges
(opção de nome estranho introduzida no bash-4.3), schily-sh
e yash
, [A-Z]
corresponde aos caracteres cujo ponto de código está entre o de A
e o de Z
, portanto seria equivalente ao comportamento do código de bash
idioma C.
Para cinzas, mksh e cascas antigas, o mesmo que zsh
acima, mas limitado a conjuntos de caracteres de byte único. Ou seja, em um código de idioma UTF-8, por exemplo, [É-Ź]
não corresponderia Ó
, mas, como isso [<c3><89>-<c5><b9>]
, corresponderia aos valores de bytes 0x89 a 0xc5!
ksh93
comporta-se como bash
exceto que trata como intervalos de casos especiais cujas extremidades começam com letras minúsculas ou maiúsculas. Nesse caso, ele corresponde apenas aos elementos de intercalação que se classificam entre essas extremidades, mas que são (ou o primeiro caractere para elementos de intercalação de vários caracteres) também em minúsculas (ou maiúsculas, respectivamente). Portanto [A-Z]
, haveria correspondência em É
, mas não em, e
como e
a classificação entre A
e Z
mas não é maiúscula como A
e Z
.
Para fnmatch()
padrões (como em find -name '[A-Z]'
) ou expressões regulares do sistema (como em grep '[A-Z]'
), isso depende do sistema e da localidade. Por exemplo, em um sistema GNU aqui, [A-Z]
não corresponde no código x
do en_GB.UTF-8
idioma, mas no th_TH.UTF-8
. Não está claro para mim quais informações são usadas para determinar isso, mas aparentemente são baseadas em uma tabela de pesquisa derivada dos dados do código de idioma LC_COLLATE ).
Todos os comportamentos são permitidos pelo POSIX, pois o POSIX deixa o comportamento dos intervalos não especificados em códigos de idioma que não sejam o código C. Agora podemos discutir sobre os benefícios de cada abordagem.
bash
A abordagem de faz muito sentido [C-G]
, pois queremos que os personagens entre C
e G
. E usar a ordem de classificação do usuário para o que determina o que é intermediário é a abordagem mais lógica.
Agora, o problema é que isso quebra as expectativas de muitas pessoas, especialmente aquelas que estão acostumadas com o comportamento tradicional do pré-Unicode, mesmo nos dias anteriores à internacionalização. Embora, para um usuário normal, faça sentido que [C-I]
inclua h
como a h
letra está entre C
e I
e que [A-g]
não inclua Z
, é uma questão diferente para as pessoas que lidam com o ASCII apenas por décadas.
Esse bash
comportamento também é diferente do [A-Z]
intervalo correspondente em outras ferramentas GNU, como nas expressões regulares do GNU (como em grep
/ sed
...) ou fnmatch()
como em find -name
.
Isso também significa que o que [A-Z]
corresponde varia de acordo com o ambiente, com o sistema operacional e com a versão do sistema operacional. O fato de [A-Z]
corresponder Á, mas não Ź também é subótimo.
Para zsh
/ yash
, usamos uma ordem de classificação diferente. Em vez de confiar na noção de ordem de caracteres do usuário, usamos os valores do código do ponto de caractere. Isso tem o benefício de ser fácil de entender, mas de um ponto prático de poucos, fora do ASCII, não é muito útil. [A-Z]
corresponde às 26 letras maiúsculas em inglês dos EUA, [0-9]
corresponde aos dígitos decimais. Existem pontos de código no Unicode que seguem a ordem de alguns alfabetos, mas isso não é generalizado e não pode ser generalizado, pois pessoas diferentes que usam o mesmo script não necessariamente concordam com a ordem das letras.
Para shells e mksh tradicionais, traço, está quebrado (agora que a maioria das pessoas usa caracteres de vários bytes), mas principalmente porque ainda não têm suporte para vários bytes. A adição de suporte de vários bytes a shells como bash
e zsh
tem sido um grande esforço e ainda está em andamento. yash
(shell japonês) foi projetado inicialmente com suporte a vários bytes desde o início.
A abordagem do ksh93 tem o benefício de ser consistente com as expressões regulares do sistema ou fnmatch () (ou pelo menos parece ser pelo menos nos sistemas GNU). Lá, isso não quebra a expectativa de algumas pessoas, pois [A-Z]
não inclui letras minúsculas, [A-Z]
inclui É
(e Á, mas não Ź). Não é consistente com sort
ou geralmente strcoll()
ordem.
locale
? Não consigo reproduzir isso (touch foo; echo [A-Z]*
gera o padrão literal, não "foo", em um diretório vazio).