Que finalidade o cólon embutido serve?

38

Eu invadi um monte de scripts de shell e, às vezes, as coisas mais simples me deixam perplexo. Hoje eu encontrei um script que fazia uso extensivo do : (colon) bash embutido.

A documentação parece bastante simples:

: (a colon)  
     : [arguments]  

Do nothing beyond expanding arguments and performing redirections. The return status is zero.

No entanto, eu só vi anteriormente isso usado em demonstrações de expansão de shell. O caso de uso no script que eu encontrei fez uso extensivo dessa estrutura:

if [ -f ${file} ]; then
    grep some_string ${file} >> otherfile || :
    grep other_string ${file} >> otherfile || :
fi

Na verdade, existem centenas de greps, mas são apenas mais do mesmo. Nenhum redirecionamento de entrada / saída está presente além da estrutura simples acima. Nenhum valor de retorno é verificado mais tarde no script.

Estou lendo isso como uma construção inútil que diz "ou não faço nada". Com que finalidade poderia terminar esses greps com "ou não fazer nada"? Em que casos essa construção causaria um resultado diferente do que simplesmente deixar de fora o || : de todas as instâncias?

    
por Caleb 14.02.2012 / 19:37

7 respostas

26

Parece que o : s no seu script está sendo usado em vez de true . Se grep não encontrar uma correspondência no arquivo, ele retornará um código de saída diferente de zero. Como jw013 menciona em um comentário, se errexit for definido, provavelmente por -e na linha shebang, o script sairá se qualquer um dos grep s não conseguir encontrar uma correspondência. Claramente, não é isso que o autor queria, então ele adicionou || : para fazer com que o status de saída daquele comando composto em particular fosse sempre zero, como o mais comum (na minha experiência) || true / || /bin/true .

    
por 14.02.2012 / 21:24
32

O : builtin também é útil com a expansão de shell Bash "assign default values", em que a expansão é geralmente usada apenas para o efeito colateral e o valor expandido é descartado:

# assign FOO=bar iff FOO is unset
: ${FOO:=bar}
    
por 15.02.2012 / 01:13
19

Posso pensar em dois lugares em que usei : no passado.

while :
do
     shell commands
     some exit condition
done

Esse é um loop contínuo.

function doSomethingStub {
    :
}

Coloque em uma função stub, apenas para obter o fluxo de controle de nível superior correto.

Um uso que eu vi nos Dias Antigos: em vez de uma linha #!/bin/sh (ou qualquer outra), você veria uma linha : . Alguns dos antigos kernels Real Unix ou Shells Real Unix usariam isso para significar "Eu sou um script de shell, tem que me rodar". Pelo que me lembro, foi exatamente quando o csh estava fazendo incursões como um shell interativo comum.

    
por 14.02.2012 / 19:42
15

O : incorporado já estava no shell Thompson - é documentado para Unix V6 em 1975. No shell Thompson, : indicou um rótulo para o comando goto . Se você nunca tentou chamar goto em uma linha que começa com , essa linha foi efetivamente um comentário.

O Bourne shell , o ancestral de shells Bourne / POSIX como os conhecemos, nunca teve um goto que Eu sei, mas mantive : como um comando no-op (ele já estava presente no Unix V7 ).

    
por 31.05.2012 / 23:01
10

Escavamos uma referência antiga: "O Ambiente de Programação do UNIX" (c) 1984 por Kernighan e Pike.

Página 147 (Programação Shell) diz isto:

":" is a shell built-in command that does nothing but elevate its arguments and return "true". Instead [referring to a script example], we could have used true, which merely returns a true exit status. (There is also a false command.) But ':' is more efficient than true because it does not execute a command from the file system. [Italics/emphasis is mine.]

    
por 10.12.2013 / 08:51
8

Eu pareço lembrar que as primeiras versões do shell não tinham uma sintaxe de comentário. Uma linha que começa com : (que provavelmente seria um executável real, semelhante a /bin/true ) teria sido a melhor alternativa.

Aqui está uma página man para o antigo Thompson shell (sem relação); não há menção de qualquer sintaxe de comentário.

    
por 14.02.2012 / 23:34
8

":" é útil para depuração.

DEBUGLOG=": debugfunction"

statement
statement
$DEBUGLOG arg1 arg2 ...
statement
statement

Rodando normalmente, a função de depuração nunca é executada, de modo que apenas os passos sobre o noop (variáveis e curingas são expandidos). Se uma depuração mais profunda for necessária, remova o noop da variável e a função debug será chamada com os argumentos necessários.

Outro uso prático é como um comentário de bloco, que é um recurso ausente da sintaxe do shell.

: << COMMENT
all --statements --in --here
are now -a here document which are
passed to --the noop
COMMENT
    
por 11.10.2013 / 17:53