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 / computer / Perguntas / 1873141
Accepted
Hubert Kauker
Hubert Kauker
Asked: 2025-01-28 02:44:52 +0800 CST2025-01-28 02:44:52 +0800 CST 2025-01-28 02:44:52 +0800 CST

zsh alternar while-loop saída inesperada

  • 772

Estou online ZSH_VERSION=5.9e tenho este script que funciona como esperado:

integer count=3
while true ; do
    echo $count
    (( count-- ))
    if (( count == 0 )) break
done
echo Finally: $count
echo ok

Ele faz a contagem regressiva de 3até 1e então diz: Finally: 0e ok.

Mas vamos substituir o do ... donebloco por um { ... }como este:

integer count=3
while true ; {
    echo $count
    (( count-- ))
    if [[ $count == 0 ]] break
}
echo Finally: $count
echo ok

Não há absolutamente nenhuma mensagem de erro, mas a saída é confusa:

3
Finally: 2
ok
2
Finally: 1
ok
1

Não tenho a mínima ideia do porquê disso, exceto que o analisador tem um problema. Ou estou usando a sintaxe alternativa while-loop errada? Isso acontece quando estou em um shell recém-iniciado.

zsh
  • 2 2 respostas
  • 64 Views

2 respostas

  • Voted
  1. Best Answer
    Gairfowl
    2025-01-28T23:25:11+08:002025-01-28T23:25:11+08:00

    As formas alternativas dos comandos complexos são mais limitadas do que as formas padrão; while truenão é suportado. Dos documentos :

    Para os ifcomandos , whilee until, ... a parte de teste do loop também deve ser delimitada adequadamente, como por [[ ... ]] ou (( ... )), caso contrário o final do teste não será reconhecido.
    ...

    As regras significam que
       if [[ -o ignorebraces ]] {
        print yes
       }
    funciona, mas
       if true { # Does not work!
        print yes
       }
    não funciona, pois o teste não é adequadamente delimitado.
    ...

    whilelist{list2}

    Uma forma alternativa de while. Observe as limitações na forma de listmencionada acima.

    Há várias maneiras de criar uma condição 'adequadamente delimitada' sempre verdadeira. Uma opção:

    integer count=3
    while ((1)) {
        echo $count
        if (( ! --count )) break
    }
    echo Finally: $count
    echo ok
    

    A parte surpreendente é que a while true; {...versão do loop produz qualquer saída, em vez de gerar uma mensagem de erro. Com base em alguns testes limitados, parece que, na ausência de qualquer um dos delimitadores adequados, o analisador simplesmente adiciona tudo após o whileaté o final do script às listcondições de. O loop resultante é provavelmente semelhante a este:

    integer count=3
    while true; echo $count; if ((! --count)) break; echo Finally: $count; echo ok
    do
    done
    

    Este loop tem vários comandos na condição list, o que é permitido pela whilesintaxe, mas quase nunca usado. Observe que o código de retorno do último comando na lista é o testado pelo while; neste caso, é um echoque retorna com sucesso. É o if...breakque encerra este loop.

    Não encontrei nenhuma documentação que descreva esse comportamento aparente de 'usar tudo até eof'. Você pode ter alguma sorte perguntando aos desenvolvedores na lista de discussão do zsh se isso é intencional, um bug de análise ou uma interpretação errônea do que está acontecendo.


    Editado para adicionar: Parece que houve alguma discussão relacionada a isso na lista de discussão em 2018 e 2024. Um patch para detectar quando não havia uma condição delimitada nunca foi aplicado, em grande parte porque o zshanalisador já imprimirá um erro nesse caso se a SHORT_LOOPSopção não estiver definida (ela é definida por padrão):

    #!/usr/bin/env zsh
    unsetopt shortloops
    while true; { print $count }
    
    >> ./tst
    ./tst:4: parse error near `\n'
    
    • 3
  2. Hubert Kauker
    2025-01-29T16:28:25+08:002025-01-29T16:28:25+08:00

    Obrigado @Gairfowl por me apontar a direção certa. O ponto e vírgula ou a nova linha simplesmente não termina uma lista , mas apenas uma sublista , após a qual mais sublistas podem seguir. Dentro de um { ... }o último ponto e vírgula ou nova linha pode ser omitido, no entanto.

    Quando o zsh analisa a while list do list done, as palavras reservadas do e done encerram as duas listas. Mas quando a while true; { list }é visto, o analisador toma true;como primeira sublista, { list }como segunda, e todos os comandos subsequentes em linhas separadas como sublistas adicionais, também, até o EOF. Acabamos tendo uma lista maior do que o pretendido para a condição de loop, e um corpo vazio do loop. Obviamente, um corpo vazio é permitido, então eu diria que esse comportamento é intencional, no geral.

    Para resumir, as seguintes construções estão funcionando conforme o esperado:

    while true; do
    done
    
    while { true } do
    done
    
    while { true; } {
    }
    
    while { true } {
    }
    
    while (( 1 )) do
    done
    
    while (( 1 )); do
    done
    
    while (( 1 )) {
    }
    

    Mas o seguinte NÃO está funcionando:

    while (( 1 )) ; {
    }
    

    Ele tem o mesmo problema de "ganância" que while true; { ... }.

    • 2

relate perguntas

  • Qual é a diferença entre $path e $PATH do zsh?

  • Alacritty + tmux não pode copiar grande parte do texto no modo de cópia

  • Comportamento estranho para a conclusão automática do zsh

  • substituindo zsh por bash no usuário não root

  • nenhum arquivo ou diretório: /Users/username/.oh-my-zsh/oh-my-zsh.sh

Sidebar

Stats

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

    Como posso reduzir o consumo do processo `vmmem`?

    • 11 respostas
  • Marko Smith

    Baixar vídeo do Microsoft Stream

    • 4 respostas
  • Marko Smith

    O Google Chrome DevTools falhou ao analisar o SourceMap: chrome-extension

    • 6 respostas
  • Marko Smith

    O visualizador de fotos do Windows não pode ser executado porque não há memória suficiente?

    • 5 respostas
  • Marko Smith

    Como faço para ativar o WindowsXP agora que o suporte acabou?

    • 6 respostas
  • Marko Smith

    Área de trabalho remota congelando intermitentemente

    • 7 respostas
  • Marko Smith

    O que significa ter uma máscara de sub-rede /32?

    • 6 respostas
  • Marko Smith

    Ponteiro do mouse movendo-se nas teclas de seta pressionadas no Windows?

    • 1 respostas
  • Marko Smith

    O VirtualBox falha ao iniciar com VERR_NEM_VM_CREATE_FAILED

    • 8 respostas
  • Marko Smith

    Os aplicativos não aparecem nas configurações de privacidade da câmera e do microfone no MacBook

    • 5 respostas
  • Martin Hope
    Vickel O Firefox não permite mais colar no WhatsApp web? 2023-08-18 05:04:35 +0800 CST
  • Martin Hope
    Saaru Lindestøkke Por que os arquivos tar.xz são 15x menores ao usar a biblioteca tar do Python em comparação com o tar do macOS? 2021-03-14 09:37:48 +0800 CST
  • Martin Hope
    CiaranWelsh Como posso reduzir o consumo do processo `vmmem`? 2020-06-10 02:06:58 +0800 CST
  • Martin Hope
    Jim Pesquisa do Windows 10 não está carregando, mostrando janela em branco 2020-02-06 03:28:26 +0800 CST
  • Martin Hope
    andre_ss6 Área de trabalho remota congelando intermitentemente 2019-09-11 12:56:40 +0800 CST
  • Martin Hope
    Riley Carney Por que colocar um ponto após o URL remove as informações de login? 2019-08-06 10:59:24 +0800 CST
  • Martin Hope
    zdimension Ponteiro do mouse movendo-se nas teclas de seta pressionadas no Windows? 2019-08-04 06:39:57 +0800 CST
  • Martin Hope
    jonsca Todos os meus complementos do Firefox foram desativados repentinamente, como posso reativá-los? 2019-05-04 17:58:52 +0800 CST
  • Martin Hope
    MCK É possível criar um código QR usando texto? 2019-04-02 06:32:14 +0800 CST
  • Martin Hope
    SoniEx2 Altere o nome da ramificação padrão do git init 2019-04-01 06:16:56 +0800 CST

Hot tag

windows-10 linux windows microsoft-excel networking ubuntu worksheet-function bash command-line hard-drive

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