AskOverflow.Dev

AskOverflow.Dev Logo AskOverflow.Dev Logo

AskOverflow.Dev Navigation

  • Início
  • system&network
  • Ubuntu
  • Unix
  • DBA
  • Computer
  • Coding
  • LangChain

Mobile menu

Close
  • Início
  • system&network
    • Recentes
    • Highest score
    • tags
  • Ubuntu
    • Recentes
    • Highest score
    • tags
  • Unix
    • Recentes
    • tags
  • DBA
    • Recentes
    • tags
  • Computer
    • Recentes
    • tags
  • Coding
    • Recentes
    • tags
Início / unix / Perguntas / 668558
Accepted
Nick Bull
Nick Bull
Asked: 2021-09-12 01:48:25 +0800 CST2021-09-12 01:48:25 +0800 CST 2021-09-12 01:48:25 +0800 CST

Por que o zsh printf não respeita a notação octal?

  • 772
sh -c 'printf "%d " 024'
bash -c 'printf "%d " 024'
zsh -c 'printf "%d" 024'

As saídas acima 20 20 24. Por que o zsh não respeita a notação octal? Existe uma maneira para mudar isso?

zsh printf
  • 3 3 respostas
  • 307 Views

3 respostas

  • Voted
  1. Best Answer
    Stéphane Chazelas
    2021-09-13T03:28:06+08:002021-09-13T03:28:06+08:00

    zshnão é um shell POSIX, ele foi escrito antes do shlançamento da especificação POSIX, pegou recursos e sintaxe de ksh, csh, tcsh, rc e adicionou muitos dos seus próprios. Sua sintaxe é em grande parte semelhante ao Korn, mas isso não significa que seja totalmente compatível com o shell Korn. De qualquer forma, não é e nunca pretendeu ser um interpretador compatível com POSIX para a linguagem sh (pelo menos não em seu modo padrão).

    No entanto, ele possui vários modos de emulação (csh, ksh e sh (anteriormente tentando seguir o SysV sh, agora seguindo o POSIX sh)) que podem ser usados ​​para melhorar a compatibilidade com outros shells e interpretar o código escrito para eles. Isso significa que ele pode ter sua própria sintaxe separada daquela de sh ou de qualquer outro shell (como csh, rc, fish, perl, python...) e ainda ser capaz de interpretar código escrito para sh.

    Se invocado como sh, csh, ou ksh(ou qualquer coisa que comece com s(ou bpara Bourne), cou k), ou em versões mais recentes com --emulate sh/ksh/csh, ele entrará no modo de emulação correspondente, mas não é assim que você normalmente os usaria. Para interpretar um shscript, você executaria sh, não zsh.

    Você prefere executar emulate shdentro zshpara alternar o modo de emulação para shquando quiser interpretar o código sh dentro de zsh, e também pode executar emulate sh -c 'some code'para ter some codeinterpretado na shemulação.

    Assim, dentro de zsh:

    emulate sh -c 'printf "%d\n" 024'
    

    seria executado printfde uma maneira mais POSIX.

    Quanto ao printf, um printfutilitário apareceu pela primeira vez em Research Unix Ninth Edition (da AT&T Research / Bell Labs, não em uso amplo) por volta de 1986, para obter a mesma API de formatação de texto disponível em C com a printffunção libc.

    Enquanto Cum leva um primeiro argumento de formato como um ponteiro para uma matriz de bytes delimitada por NUL e argumentos extras de diferentes tipos (ponteiro, inteiro, duplo...), um executável só pode receber argumentos como strings. Portanto, para formatar um número, por exemplo, para %d, ele precisa receber uma representação de texto de um número e convertê-lo de volta em um inteiro binário e convertê- printflo de volta em texto para saída.

    Na implementação original em V9 , printfreconhecia os mesmos números que na linguagem C (dec -123, +123, octal 0123, hex 0x123, float 1.2e-2, even 'x'or "foo"(onde é o valor do primeiro caractere usado)).

    O SVR4 (descendente do V7) também tinha um printfutilitário muito burro que acabou de fazer:

            printf(fmt, argv[2], argv[3], argv[4],  argv[5],
                            argv[6], argv[7], argv[8], argv[9],
                            argv[10], argv[11], argv[12], argv[13],
                            argv[14], argv[15], argv[16], argv[17],
                            argv[18], argv[19], argv[20]);
    

    Portanto, era útil apenas para %sformatação de tipo, pois printf()apenas eram fornecidos ponteiros para os argumentos de string.

    POSIX.2 (escrito no final dos anos 80 atrás de portas (principalmente) fechadas e lançado em 1992 (não disponível gratuitamente na época)), especificou um printfcomando. Como o echoutilitário era muito pouco portátil e não confiável, uma alternativa era muito necessária. Por alguma razão, eles não optaram kshpelo printbuilt-in do , mas especificaram um printfutilitário baseado principalmente na implementação da V9 e com uma referência à linguagem C quando se trata de converter strings em números.

    ksh88, o shell no qual a shespecificação POSIX é baseada nunca teve um printfbuilt-in (nem seu clone pdksh). Ele tem seu próprio printbuilt-in como uma alternativa confiável para echo. Uma -fopção para printfoi adicionada em ksh93 junto com um printfalias para print -f.

    No ksh, a maioria dos builtins ou construções que aceitam números como entrada aceitará qualquer expressão aritmética, não apenas constantes numéricas. Então, em ksh93

    printf '%d\n' '1 + 1'
    

    Iria imprimir 2.

    E nas primeiras versões, printf '%d\n' 010imprimiria 10, não 8.

    Nas expressões aritméticas do shell ksh, inicialmente, os números com 0s iniciais não eram considerados octais porque, em um shell, é muito mais comum lidar com números decimais preenchidos com 0 (como data/hora, nomes de arquivos) do que lidar com números octais.

    No entanto, a especificação POSIX meio que exigia que eles fossem tratados como octais, o que a maioria dos shells ignorou (como a implementação original do shell no qual o padrão foi baseado não). No entanto, após a Solicitação de Interpretação do PASC que tornou mais claro, a maioria dos shells começou a mudar seu comportamento (incluindo ksh93 e zsh, embora isso tenha sido revertido ), causando muita dor.

    Se você observar o histórico de lançamentos de ksh93 , você notará que o tratamento de números com prefixo 0 como octal foi ativado e desativado. Ainda hoje, você descobrirá que 010 em expressões aritméticas é 8 dentro de ((...))ou $((...)), mas 10 na maioria dos outros lugares, incluindo let '...', array[...], [[ ... -eq ... ]]e... printf. set -o posixfaz com que mude para 8 na maioria dos lugares, sendo uma exceção notável... printfnovamente .

    Como o zsh nunca afirmou ser um shell POSIX, ele apenas adicionou uma nova opção ( octal_zeroes) em 2000, habilitada na shemulação, mas não de outra forma.

    Um printfbuiltin foi adicionado mais tarde em 2001, inicialmente usandostrtod() para converter texto em números, tratando números com 0 à esquerda como octal, mas depois alterado para aceitar qualquer expressão aritmética como em ksh93, sujeito às octal_zeroesopções e permitindo mais formatos numéricos, como 0b10010, ksh -style números baseados arbitrários ( 12#A001, 2#10010...), 1_000_000...

    Então, em zsh, para passar um número octal para printf, as opções são:

    • emular she usar 0 inicial:emulate sh -c 'printf %d 024'
    • defina a octalzeroesopção:set -o octalzeroes; printf %d 024
    • mesmo em um escopo local apenas: (){ set -o localoptions -o octalzeroes; printf %d 024; }(aqui em uma função anônima).
    • use a 8#oooonotação que é sempre reconhecida:printf %d '8#24'
    • desabilite o printfbuilt-in e assuma que o printfutilitário do sistema é compatível com POSIX a esse respeito: disable printf; printf %d 024.
    • Outras maneiras de invocar esse autônomo printf: command printf %d 024(não em shemulação), =printf %d 024(não em shemulação).
    • 5
  2. Random832
    2021-09-12T02:17:41+08:002021-09-12T02:17:41+08:00

    Use command printf ...para executar o utilitário printf padrão. printf de zsh tem suas próprias interpretações de argumentos que entram em conflito com o padrão POSIX, %d interpreta argumentos como expressões aritméticas, então você pode converter um valor de octal com printf %d '8#24'.

    • 1
  3. schily
    2021-09-12T02:21:19+08:002021-09-12T02:21:19+08:00

    zsh não é compatível com POSIX por padrão e os desvios não são apenas pequenos.

    Este é um problema geral com o uso de zsh.

    Tentar:

    zsh --emulate sh -c 'printf "%d\n" 024'
    

    e imprimirá 20

    Mas note que isso só funcionará com uma zshversão recente.

    Se você gosta de um método que funcione mesmo com zshversões mais antigas, existe uma maneira de fazer isso. Crie um arquivo $HOME/.zshenvcom o seguinte conteúdo:

    if [ -n "$ZSH_EMULATION" ]; then
        emulate "$ZSH_EMULATION"
    fi
    

    Se você tiver esse arquivo, você pode chamar:

    ZSH_EMULATION=sh zsh -c 'printf "%d\n" 024'
    

    e isso funcionará com qualquer versão do zsh.

    BTW: o texto atual relacionado ZSH_EMULATIONfoi introduzido após uma discussão nos comentários.

    • 0

relate perguntas

  • Em que circunstâncias o executável encontrado primeiro no caminho não será usado

  • Symlinking para todos os arquivos de ponto e diretórios

  • Como incrementar uma variável nomeada dinamicamente em `zsh`

  • Por que não consigo definir uma variável somente leitura chamada path no zsh?

  • Como produzir em colunas usando `printf` interno do Bash, onde a fonte contém cores?

Sidebar

Stats

  • Perguntas 205573
  • respostas 270741
  • best respostas 135370
  • utilizador 68524
  • Highest score
  • respostas
  • Marko Smith

    Possível firmware ausente /lib/firmware/i915/* para o módulo i915

    • 3 respostas
  • Marko Smith

    Falha ao buscar o repositório de backports jessie

    • 4 respostas
  • Marko Smith

    Como exportar uma chave privada GPG e uma chave pública para um arquivo

    • 4 respostas
  • Marko Smith

    Como podemos executar um comando armazenado em uma variável?

    • 5 respostas
  • Marko Smith

    Como configurar o systemd-resolved e o systemd-networkd para usar o servidor DNS local para resolver domínios locais e o servidor DNS remoto para domínios remotos?

    • 3 respostas
  • Marko Smith

    apt-get update error no Kali Linux após a atualização do dist [duplicado]

    • 2 respostas
  • Marko Smith

    Como ver as últimas linhas x do log de serviço systemctl

    • 5 respostas
  • Marko Smith

    Nano - pule para o final do arquivo

    • 8 respostas
  • Marko Smith

    erro grub: você precisa carregar o kernel primeiro

    • 4 respostas
  • Marko Smith

    Como baixar o pacote não instalá-lo com o comando apt-get?

    • 7 respostas
  • Martin Hope
    user12345 Falha ao buscar o repositório de backports jessie 2019-03-27 04:39:28 +0800 CST
  • Martin Hope
    Carl Por que a maioria dos exemplos do systemd contém WantedBy=multi-user.target? 2019-03-15 11:49:25 +0800 CST
  • Martin Hope
    rocky Como exportar uma chave privada GPG e uma chave pública para um arquivo 2018-11-16 05:36:15 +0800 CST
  • Martin Hope
    Evan Carroll status systemctl mostra: "Estado: degradado" 2018-06-03 18:48:17 +0800 CST
  • Martin Hope
    Tim Como podemos executar um comando armazenado em uma variável? 2018-05-21 04:46:29 +0800 CST
  • Martin Hope
    Ankur S Por que /dev/null é um arquivo? Por que sua função não é implementada como um programa simples? 2018-04-17 07:28:04 +0800 CST
  • Martin Hope
    user3191334 Como ver as últimas linhas x do log de serviço systemctl 2018-02-07 00:14:16 +0800 CST
  • Martin Hope
    Marko Pacak Nano - pule para o final do arquivo 2018-02-01 01:53:03 +0800 CST
  • Martin Hope
    Kidburla Por que verdadeiro e falso são tão grandes? 2018-01-26 12:14:47 +0800 CST
  • Martin Hope
    Christos Baziotis Substitua a string em um arquivo de texto enorme (70 GB), uma linha 2017-12-30 06:58:33 +0800 CST

Hot tag

linux bash debian shell-script text-processing ubuntu centos shell awk ssh

Explore

  • Início
  • Perguntas
    • Recentes
    • Highest score
  • tag
  • help

Footer

AskOverflow.Dev

About Us

  • About Us
  • Contact Us

Legal Stuff

  • Privacy Policy

Language

  • Pt
  • Server
  • Unix

© 2023 AskOverflow.DEV All Rights Reserve