Por que a substituição de variável bash-extended-globbing está atuando no nível de byte?

7

Eu pensei que a substituição de variáveis bash e a globbing funcionavam na resolução caractere , então fiquei bastante surpreso ao vê-la atuando no nível byte . Tudo no meu locale é en_AU.UTF-8

Quando não há nada para combinar e o padrão permite zero-para-muitos, a substituição ocorre no nível byte , como visto pelas substituições subsequentes. Eu esperava que ele fosse para o próximo , mas não ...

Talvez este seja apenas um padrão de maluco, ou eu estou perdendo algo óbvio, mas eu me pergunto o que está acontecendo aqui, e posso esperar esse comportamento em outro lugar além desse padrão em particular?

Aqui está o script (que começou como uma tentativa de dividir uma string em caracteres).
Eu esperava que o último teste, com o caractere , acabasse com apenas um espaço único precedendo o , mas, em vez disso, os 3 bytes UTF-8 do personagem são precedidos por um espaço . Isso resulta em saída UTF-8 inválida.

shopt -s extglob
for str in  $'\t' "ab"  ळ ;do
    printf -- '%s' "${str//*($'\x01')/ }" |xxd
done

Saída:

0000000: 2009                                      .
0000000: 2061 2062                                 a b
0000000: 20e0 20a4 20b3                            . . .
    
por Peter.O 14.02.2012 / 18:22

1 resposta

4

A resposta curta à sua pergunta é que * (lista de padrões) corresponderá a zero ou mais ocorrências dos padrões fornecidos. Existem zero instâncias do caractere Unicode 0001 entre cada um dos bytes de entrada. Portanto, a operação de substituição substitui cada uma dessas ocorrências zero por um único espaço.

Talvez você quisesse fazer isso:

$ for str in  $'\t' "ab"  ळ ; do  
    printf -- '%s' "${str//+($'\x01')/ }" |xxd
  done)
0000000: 09                                       .
0000000: 6162                                     ab
0000000: e0a4 b3                                  ...

Mas a resposta mais longa é que, em qualquer caso, nomes de caminho não são texto. Pelo menos, eles não estão tão longe quanto o sistema operacional (semelhante ao Unix) está em causa. Eles são seqüências de bytes. O problema é que coisas assim são triviais:

$ LC_ALL=latin1
$ mkdir 'áñ' && cd 'áñ'
$ LC_ALL=ga_IE.iso885915@euro
$ mkdir '€25' && cd '€25'
$ LC_ALL=zh_TW
$ pwd
# ... what should the output be?  And what about the output of:
$ /bin/pwd

Cada uma dessas localidades inclui caracteres que não existem nos outros. Esse problema afeta coisas como locate -r e localizar -regex também; o argumento de locate -r é uma expressão regular que, portanto, deve incluir suporte para coisas como classes de caracteres; mas você não sabe qual localidade usar para determinar as classes de caracteres para os caracteres nos nomes de caminho ou mesmo se houver um único local utilizável que possa ser usado para representar todos os caminhos no sistema.

    
por 29.02.2012 / 00:11