1 pontos por GN⁺ 2 시간 전 | 1 comentários | Compartilhar no WhatsApp
  • O : do shell é um comando nulo (null command) que não executa nenhuma ação e apenas avalia os argumentos; combinado com expansão de parâmetros, permite lidar de forma concisa com a verificação de argumentos obrigatórios e a definição de valores padrão
  • : "${1:?missing argument, aborting!}" imprime uma mensagem de diagnóstico em stderr e encerra com status diferente de 0 se $1 estiver ausente ou vazio
  • Ao passar ${VAR:=default} como argumento de :, a expansão é executada, mas a string resultante é descartada; assim, é possível definir apenas o valor padrão sem executar o resultado da expansão como comando
  • : também pode ser usado para esvaziar arquivos via redirecionamento e verificar acessibilidade, como comando vazio em trap, para verificar variáveis em ambientes com set -u e em ramificações condicionais vazias
  • : "${VAR:=default}" reduz a chance de erros de digitação ao escrever o nome da variável apenas uma vez; em while :, torna-se uma condição sempre bem-sucedida e expressa um loop infinito

Comando nulo e expansão de parâmetros

  • : é um comando interno nulo que avalia os argumentos e descarta o resultado
    • Remonta ao Thompson shell, de 1971, e na época também era usado como rótulo e como o primeiro marcador de comentário do Unix
  • Em vez de uma condicional de quatro linhas, é possível verificar um argumento obrigatório com a seguinte linha única
: "${1:?missing argument, aborting!}"
echo "Hello $1!"
  • A sintaxe de expansão de parâmetros ${name:?diagnostic} verifica se $name não foi definido ou está vazio
    • Se não houver valor, imprime diagnostic em stderr e encerra o shell com status diferente de 0
    • Se houver valor, produz o mesmo resultado que $name
  • Se ${HELLO:=123} for executado sozinho, sem o comando nulo, o resultado da expansão, 123, será tratado como comando e causará command not found
    • : ${HELLO:=123} avalia a expansão, define HELLO=123 e descarta o resultado
  • : "${DATA_DIR:=/var/data}", ao contrário de DATA_DIR="${DATA_DIR:-/var/data}", exige escrever o nome da variável apenas uma vez, reduzindo a chance de erros de digitação como DATA_DRI

Como usar :

  • Definição de valores padrão

    • Define valores padrão de variáveis enquanto descarta o resultado da expansão, sem executá-lo
: "${DATA_DIR:=/var/data}"
: "${RETRIES:=3}"
  • Esvaziar arquivos e verificar acesso

    • Combinado com redirecionamento, pode esvaziar um ou mais arquivos
: > error.log
: > error.log > access.log
  • Usando subshell e redirecionamento, também é possível verificar se um arquivo pode ser lido ou escrito
( : < dataset.json ) && echo YES
( : >> result.json ) && echo YES
  • Locais que exigem um comando vazio

    • Pode ser usado quando a sintaxe exige um comando, como em trap, mas nenhuma ação real deve ser executada
trap : INT
sleep 60
  • Também pode ser colocado em ramificações que devem ficar vazias em condicionais
if some-command; then
    :
else
    echo "command failed"
fi
  • Verificação de várias variáveis

    • Com set -u ativado, verifica de uma só vez se várias variáveis foram definidas
set -u
: "$DEPLOY_ENV" "$HOST"
  • Loop infinito

    • Como : é uma condição que sempre tem sucesso, permite escrever um loop infinito de forma concisa
while :; do
  echo "I love colons"
  sleep 1
done

1 comentários

 
GN⁺ 2 시간 전
Comentários no Lobste.rs
  • Se você configurar o prompt assim, mesmo copiando e colando a linha inteira, a parte do prompt é ignorada e só o comando é executado
    : hayalci@tassadar ~/src/dool ; jj rebase -s dxw -d mrn
    • Inspirado no Plan 9, também se usa a opção autocd do shell e o seguinte formato
      ~/directoryname; <command>
      Sempre que copiar a linha de comando do shell, ele continua dando cd para o diretório onde o comando foi executado originalmente
    • No zsh, a configuração faz com que, ao colar um espaço sem quebra de linha invisível, o conteúdo à esquerda seja apagado
      nbsp=$'\u00A0'  
      PS1="...$nbsp"  
      bindkey -s $nbsp '^u'  
      
  • Em Makefiles, dois-pontos são usados com frequência para uma saída visualmente agradável
    out/%.o: src/%.c  
        @echo CC $@  
        @$(CC) -c -o $@ $<  
    
    Desse jeito, o make pode executar vários processos echo ao mesmo tempo, escrevendo no mesmo stream e interferindo uns nos outros. Se mudar para o formato abaixo, quem imprime é o próprio processo make, não um processo filho
    out/%.o: src/%.c  
        : CC $@  
        @$(CC) -c -o $@ $<  
    
  • Já vi essa técnica em scripts de shell, mas era difícil encontrar documentação útil com man : ou whatis :
    É parecido com o comando true, mas a diferença é que não reage de forma especial a --help, --version etc., além de ter menos caracteres
    • Comandos embutidos do Bash devem ser consultados com help, em vez de man
      $ help :  
      :: :  
          Null command.
      
          No effect; the command does nothing.
      
          Exit Status:  
          Always succeeds.  
      
    • No Fish, : é literalmente um alias de true
  • A expansão de parâmetros acontece mesmo sem os dois-pontos; então fica a dúvida de por que é necessário um comando nulo
    • A expansão de parâmetros realmente acontece, mas, se não houver uma construção que consuma o resultado como o comando nulo faz, o shell trata a string expandida como um comando a executar. Isso também foi adicionado ao FAQ
      % ${HELLO:=123}  
      zsh: command not found: 123  
      
      % : ${HELLO:=123}  
      % echo $HELLO  
      123  
      
    • O resultado da string interpolada é interpretado como o comando a executar
      #!/bin/sh  
      "${1:?missing argument, aborting!}"  
      
      $ sh foo.sh sh  
      sh-5.3$  
      
  • Quando estou digitando um comando e quero executá-lo mais tarde, coloco dois-pontos no começo da linha para salvá-lo no histórico. Depois encontro essa linha no histórico e apago só o primeiro caractere para executá-la de verdade
    Porém, eu não tinha pensado em usar isso para efeitos colaterais causados pela avaliação dos argumentos
    • Em vez de :, também é possível prefixar com # e salvar como comentário. Se for algo para executar depois, isso tem a vantagem de não avaliar previamente as expressões dentro dele
    • No zsh, com Meta-q ou Alt-q, você pode tirar temporariamente a linha atual do caminho, executar outro comando e, quando ele terminar, devolver a linha original ao buffer da linha de comando
      https://nathangrigg.com/2014/04/zsh-push-line-or-edit/
  • No macOS, ainda usando Bash 3, ocorre o seguinte erro
    -bash: !}": event not found
    • Fico curioso se funciona ao remover o uso de "!"
  • O código abaixo em Con-colon-sion provavelmente confunde mais as pessoas do que while true; do...
    while : colons are more than punctuation; do  
      echo "I love colons"  
      sleep 1  
    done  
    
    while true; do tem só três caracteres a mais que while :; do, então já é curto o suficiente; esse código não parece um bom exemplo para o ponto que o autor quer transmitir
    • Não é um exemplo para seguir ao pé da letra, é um código incluído como trocadilho. Se você consegue entendê-lo, então conhece o comando nulo, e dois-pontos realmente têm mais significado do que apenas pontuação
    • O que se queria mostrar originalmente era um loop infinito como o abaixo, mas parece que, ao tentar deixar a coisa elegante, o ponto principal se perdeu
      while :; do  
          something  
      done