O que varia como A-Z ou а-я correspondência não é especificado por POSIX diferente da localidade POSIX (para A-Z , não а-я obviamente).
Somente na localidade POSIX você pode obter a garantia de que [A-Z] corresponde apenas aos caracteres ABCDEFGHIJKLMNOPQRSTUVWXYZ .
Em outras localidades, o comportamento varia entre as implementações. Alguns podem corresponder a qualquer elemento de intercalação (podem ser caracteres ou sequências de caracteres) que classifica após A e antes de Z (pode incluir ch , x ou Á , mas não Ź por exemplo) , ou eles poderiam corresponder em caracteres cujo ponto de código é maior que o de A e menor que o de Z no conjunto de caracteres do locale, ou eles poderiam usar os dados de agrupamento de localidade de uma maneira diferente ... Observe também que nem todos concordam com a ordem das letras para qualquer script (como o latim ou o cirílico nesse caso), então você terá diferentes comportamentos para diferentes localidades que incluam esses scripts no conjunto de caracteres (mesmo que seja o mesmo conjunto de caracteres)) .
Se você quiser corresponder qualquer caractere alfabético em qualquer script, use [[:alpha:]] , se quiser corresponder intervalos de caracteres com base no ponto de código em UTF-8, tente usar o C.UTF-8 locale disponível em muitos sistemas.
Se você quiser corresponder em qualquer letra do alfabeto latino, use perl ou pcre \p{Latin} (inclui é , Ê ...). Em zsh :
set -o rematchpcre
[[ $x =~ '^(\p{Latin}|\p{Cyrillic})$' ]]
Você pode restringir a letra latina àquelas encontradas somente em ASCII com (ainda com zsh e ainda com rematchpcre ):
[[ $x =~ '^((?=[[:ascii:]])\p{Latin}|\p{Cyrillic})$' ]]
embora em vigor com rematchpcre , ^([a-zA-Z]|\p{Cyrillic})$ teria o mesmo efeito, pois os intervalos em PCRE e em zsh são baseados no valor codepoint e essas letras têm a garantia de ter os mesmos pontos de código e estar nesse idioma. seqüência de alfabeto com todas as localidades em sistemas POSIX baseados em ASCII e baseados em EBCDIC, pelo menos.
Ou você pode listar os caracteres explicitamente se quiser apenas um subconjunto, para evitar toda ambigüidade:
[[ $x =~ ^[ABC...XYZabc...xyzабв...эюя]$ ]]
Você sempre pode armazená-los em variáveis como:
ascii_upper=ABC...XYZ
ascii_lower=abc...xzy
cyr_upper=...
[[ $x =~ ^[$ascii_upper$ascii_lower$cyr_upper...]$ ]]