Por que apenas algumas letras são consideradas números inválidos no printf de bash?

0

Eu estava brincando e esqueci de excluir uma seção de uma instrução printf e obtive esta saída:

# printf '%*s%c' {A..Z}
bash: printf: A: invalid number
bash: printf: D: invalid number
bash: printf: G: invalid number
bash: printf: J: invalid number
bash: printf: M: invalid number
bash: printf: P: invalid number
bash: printf: S: invalid number
bash: printf: V: invalid number
bash: printf: Y: invalid number
BCEFHIKLNOQRTUWXZ

Por que BCEFHIKLNOQRTUWXZ considera números válidos? Eu pensei que era porque eles poderiam ser caracteres de formato, mas isso não parece explicar Z .

Existe algum lugar onde eu possa ler / aprender mais sobre isso?

Informações do sistema:

  • GNU bash, versão 4.4.12 (1) -release (x86_64-desconhecido-linux-gnu)
por Grayson Kent 28.08.2017 / 14:10

1 resposta

4

A especificação do formato %*s consome dois argumentos, como em C, um para a largura de preenchimento e um para a cadeia a ser preenchida.

O utilitário printf mantém a reutilização do formato, se houver argumentos remanescentes depois que as rodadas anteriores os tiverem consumido:

Isso é para ser usado, por exemplo, como:

$ printf '%*s%c' 3 x1 '|' 4 y1  '|' 3 z1 "$NL" \
                 3 x2 '|' 4 y22 '|' 3 z2 "$NL"
 x1|  y1| z1
 x2| y22| z2

Para formatar saída em colunas. Agora, para o que é esperado como esses argumentos de largura, o comportamento depende da implementação printf .

  • Para a incorporação de zsh e AT & T ksh , essa pode ser qualquer expressão aritmética (como na maioria dos lugares que esperam um número). Então, 1+1 ou 2 significam o mesmo. A como expressão aritmética resolve o valor de $A , ou 0 é $A não está definido ou está vazio.
  • O GNU printf e o printf incorporado em bash e dash aceitam apenas as constantes literais decimais, octais ou hexadecimais (portanto, 020, 16 e 0x10 significam o mesmo) com espaços em branco iniciais (mas não ocultos) ignorados e retornar uma mensagem de erro (mas, caso contrário, use qualquer número válido, se encontrado no início do argumento, ou 0, se nenhum), se não for reconhecido como um número válido.
  • yash printf incorporado atualmente não suporta %*s

Então:

printf '%*s%c' A B C

A saída seria BC em ksh e zsh a menos que $A contenha uma expressão aritmética que resolva um número com uma parte inteira diferente de 0.

$ A=5.2*2 zsh -c "printf '%*s%c' A B C"
         BC

E a saída BC em bash / dash / GNU, mas também uma mensagem de erro, pois A não é uma constante literal decimal / octal / hexadecimal válida.

zsh ou ksh poderia gerar mensagens de erro se a expressão aritmética for inválida e, como em qualquer lugar, uma expressão aritmética for avaliada, também poderá executar comandos arbitrários com as variáveis erradas no ambiente:

$ A=1+ zsh -c "printf '%*s%c' A B C"
zsh:1: bad math expression: operand expected at end of string
BC
$ A='psvar[0$(uname>&2)]' zsh -c "printf '%*s%c' A B C"
Linux
BC
    
por 28.08.2017 / 15:00

Tags