Sensibilidade a maiúsculas e minúsculas em globbing com colchetes

9

Normalmente, bash globbing diferencia maiúsculas de minúsculas:

$ echo c*
casefix.pike cdless chalices.py charconv.py chocolate.pike circum.py clip.pike cpustats.pike crop.pike cwk2txt.py
$ echo C*
CarePackage.md ChocRippleCake.md Clips

O uso de colchetes parece não mudar isso:

$ echo [c]*
casefix.pike cdless chalices.py charconv.py chocolate.pike circum.py clip.pike cpustats.pike crop.pike cwk2txt.py
$ echo [C]*
CarePackage.md ChocRippleCake.md Clips

Ainda não é alterado se for usado um hífen:

$ echo [c-c]*
casefix.pike cdless chalices.py charconv.py chocolate.pike circum.py clip.pike cpustats.pike crop.pike cwk2txt.py
$ echo [C-C]*
CarePackage.md ChocRippleCake.md Clips

Mas as letras estão intercaladas:

$ echo [B-C]*
CarePackage.md casefix.pike cdless chalices.py charconv.py chocolate.pike ChocRippleCake.md circum.py clip.pike Clips cpustats.pike crop.pike cwk2txt.py
$ echo [b-c]*
beehive-anthem.txt bluray2mkv.pike branch branchcleanup.pike burdayim.pike casefix.pike cdless chalices.py charconv.py chocolate.pike circum.py clip.pike cpustats.pike crop.pike cwk2txt.py

Isso sugere que o hífen está usando uma ordem de localidade, "AaBbCcDd". Então, existe alguma maneira de glob para todos os arquivos que começam com uma letra maiúscula?

    
por rosuav 17.06.2017 / 23:30

5 respostas

11

Na versão bash 4.3 e posterior, existe uma opção shopt chamada globasciiranges :

De acordo com as páginas de manuais internos do gnu na loja :

globasciiranges
If set, range expressions used in pattern matching bracket expressions (see Pattern Matching) behave as if in the traditional C locale when performing comparisons. That is, the current locale’s collating sequence is not taken into account, so ‘b’ will not collate between ‘A’ and ‘B’, and upper-case and lower-case ASCII characters will collate together.

Como resultado, você pode

$ shopt -s globasciiranges 
$ echo [A-Z]*

Use shopt -u para desativar.

Outra maneira é alterar o código de idioma para C. Você pode fazer isso temporariamente usando um subshell:

$ ( LC_ALL=C ; printf '%s\n' [A-Z]*; )

Você obterá os resultados necessários e, quando o sub shell terminar, o local do seu shell principal permanecerá inalterado para o que foi antes.

Outra alternativa é, em vez de [A-Z] , usar a expansão de concha {A..Z} junto com a opção nullglob bash shopt.

Ao ativar a opção nullglob , se um padrão não for correspondido durante a expansão do nome do caminho, uma cadeia nula será retornada em vez do próprio padrão.
Como resultado, este funcionará como esperado:

$ shopt -s nullglob;printf '%s\n' {A..Z}*
    
por 17.06.2017 / 23:38
5

Você pode escrever todas as letras maiúsculas como:

[ABCDEFGHIJKLMNOPQRSTUVWXYZ]*

ou use pode usar a classe de caracteres nomeados [:upper:] para representar todas as letras maiúsculas no seu% atual locale :

[[:upper:]]*

Como você observou, ao usar o intervalo como [B-C] , as letras maiúsculas e minúsculas do mesmo caractere alfabético estão sendo organizadas de forma adjacente (de acordo com a ordem de agrupamento do locale ).

    
por 17.06.2017 / 23:51
3

A inclusão de caracteres "não intuitivos" nos intervalos de caracteres, como incluir letras minúsculas em um intervalo cujos limites são letras maiúsculas, deve-se à configuração LC_COLLATE locale. LC_COLLATE deve indicar a ordem de classificação, mas faz um trabalho ruim (as cadeias de caracteres de classificação são mais complexas do que as localidades podem fazer) e você está melhor sem ela. Eu recomendo remover LC_COLLATE de suas configurações de localidade. Se você estiver definindo LANG ou LANGUAGE , não faça isso e defina apenas os que você precisa: LC_CTYPE , LC_MESSAGES , LC_TIME .

Para obter mais informações sobre localidades, consulte O que devo definir minha localidade e quais são as implicações de fazê-lo? e conjunto LC_ * mas não LC_ALL

Para obter resultados confiáveis em um script, independentemente das configurações do usuário, defina LC_ALL=C .

    
por 18.06.2017 / 01:02
0

Definir:

shopt -u nocaseglob

Da página man do bash:

>     nocaseglob
>         If  set,  bash matches filenames in a case-insensitive
>         fashion when performing pathname expansion (see Pathname
>          Expansion above).

Se você definir 'globasciiranges', não sei o que acontecerá para caracteres não-ascii como utf-8

    
por 19.06.2017 / 16:36
0

echo [cC] * deve fazer o que você quiser, da mesma forma [A-Za-z] *

Estou aqui porque globbing no meu sistema acabou de parar sendo sensível a maiúsculas e minúsculas, então muitos dos meus scripts não funcionam mais como deveriam: - (

    
por 08.12.2018 / 17:38