Você está usando o UTF-8. Yay! ASCII, e por extensão UTF-8 (porque o pessoal da UTF tentou torná-lo um superconjunto de ASCII), tem os alfabetos em ordem alfabética sem intervalos, então a-z
contém todos os caracteres minúsculos normais e nada mais, e assim por diante .
No entanto, isso não precisa ser verdade em alguma outra codificação. O exemplo clássico é EBCDIC :
As lacunas entre as letras fizeram com que o código simples que funcionava em ASCII falhasse EBCDIC. Por exemplo,
for (c='A';c<='Z';++c)
configurariac
para o 26 letras no alfabeto ASCII, mas 40 caracteres incluindo um número de não atribuídos em EBCDIC. Corrigindo isto requer complicando o código com chamadas de função que foi muito resistido por programadores.
Eu gostaria de pensar que ninguém usa coisas estranhas como essa, mas quem sabe?
O GNU tr não suporta Unicode, AFAIK, mas para programas que possuem, [[:upper:]]
também corresponderia a caracteres Unicode considerados alfabetos maiúsculos, por exemplo, um "A" de largura total ou um A com um sotaque : À.
$ printf "%s\n" A a A À | grep '[[:upper:]]'
A
A
À
$ printf "%s\n" A a A À | grep '[A-Z]' # I'm also using Unicode, so grep tries to be friendly
A
À
$ printf "%s\n" A a A À | LC_ALL=C grep '[A-Z]'
A