Comentários sobre scripts de shell multilinha - como isso funciona?

92

Recentemente, deparei-me com um tipo de comentário multilinha que nunca vi antes - aqui está um exemplo de script:

echo a
#
: aaa 
: ddd 
#
echo b

Isso parece funcionar, até a vimsintaxe destaca. Como é chamado esse estilo de comentário e como encontro mais informações sobre ele?

Wiesław Herr
fonte
1
E se você, em vez disso, agrupar seu código em função para comentá-lo? CommentedOutBlock() { echo "test"; }
Buksy

Respostas:

135

Esse não é um comentário de várias linhas. #é um comentário de linha única. :(dois pontos) não é um comentário, mas um comando interno do shell que é basicamente um NOP , uma operação nula que não faz nada, exceto retornar true, como true(por exemplo, definir $?0 como um efeito colateral). No entanto, como é um comando, ele pode aceitar argumentos e, como ignora seus argumentos, na maioria dos casos age superficialmente como um comentário. O principal problema desse kludge é que os argumentos ainda são expandidos, levando a uma série de consequências não intencionais. Os argumentos ainda são afetados por erros de sintaxe, os redirecionamentos ainda são executados e, portanto, : > fileserão truncados filee as : $(dangerous command)substituições ainda serão executadas.

A maneira menos surpreendente e completamente segura de inserir comentários em scripts de shell é com #. Atenha-se a isso mesmo para comentários de várias linhas. Nunca tente (ab) usar :para comentários. Não existe um mecanismo de comentário de várias linhas dedicado no shell que seja análogo à /* */forma de estrela de barra em Cidiomas semelhantes.


Por uma questão de completude, mas não porque é uma prática recomendada, mencionarei que é possível usar os documentos aqui para fazer "comentários" multilinhas:

: <<'end_long_comment'
This is an abuse of the null command ':' and the here-document syntax
to achieve a "multi-line comment".  According to the POSIX spec linked 
above, if any character in the delimiter word ("end_long_comment" in 
this case) above is quoted, the here-document will not be expanded in 
any way.  This is **critical**, as failing to quote the "end_long_comment" 
will result in the problems with unintended expansions described above. 
All of this text in this here-doc goes to the standard input of :, which 
does nothing with it, hence the effect is like a comment.  There is very 
little point to doing this besides throwing people off.  Just use '#'.
end_long_comment
jw013
fonte
29
+1 é muito importante para manter as aspas simples na <<linha - isso desativa a substituição e a expansão.
glenn jackman
4
E como uma observação extra, o preenchimento de scripts de shell com :itens que devem ser comentários causará um consumo extra de RAM / CPU. Não vai agradar a coisas simples em sua área de trabalho, mas se for algo executado centenas ou milhares de vezes por segundo, você não fará nada, muito rápido .
bahamat
3
@bahamat: se você executar centenas algo ou milhares de vezes por segundo, eu espero que você não vai escrevê-lo com casca ... = /
7heo.tk
1
Às vezes, o uso do utilitário nulo para várias linhas de texto pode ser útil. Iniciar o comentário com : <<=cutpermite escrever POD em scripts de shell, consulte este exemplo para obter detalhes . Isso torna possível o uso perldoc script.sh. No entanto, o comentário de várias linhas mostrado nesta resposta é algo que definitivamente deve ser um bloco de comentários (cada linha começando com # ).
usar o seguinte comando
Aqui está uma boa discussão sobre heredocs, usada para comentários e outros casos de uso interessantes (incluindo inclusive a geração de scripts dynaimc): tldp.org/LDP/abs/html/here-docs.html#EX71C
bguiz
28

Não é nenhum estilo de comentar. o :comando interno não faz absolutamente nada; está sendo abusado por comentar aqui.

$ help :
:: :
    Null command.

    No effect; the command does nothing.

    Exit Status:
    Always succeeds.
Ignacio Vazquez-Abrams
fonte
25

Nos primeiros anos, o cólon era a única maneira de criar comentários.

No entanto, não é um comentário verdadeiro, porque a linha é analisada exatamente da mesma maneira que qualquer outro comando, e que pode ter efeitos colaterais. Por exemplo:

: ${a:=x} # assigns the value 'x' to the variable, 'a'

: $(command) # executes 'command'

(Às vezes, o cólon é usado apenas com o objetivo de invocar esses efeitos colaterais, mas depois não está sendo usado como comentário.)

Às vezes, é conveniente usar dois pontos para comentar uma seção de um script:

: '
while [ "$n" -ne "$x" ]
do
  : whatever
done
'

Isso economiza bastante o tempo que precede cada linha #, principalmente se os comentários forem apenas temporários.

Chris FA Johnson
fonte
2
Esse método de comentário de aspas simples não funciona em nenhuma seção do script que usa aspas simples. E se você estiver usando aspas em qualquer lugar próximo do quanto deveria, isso significa que você terá aspas simples legítimas espalhadas por todo o script. É muito mais simples usar qualquer editor decente que permita bloquear comentários em linha.
Jw013
Você está certo de que isso só funcionará se não houver aspas simples na seção citada. No entanto, um script não precisa ter muitas aspas simples. Ao examinar alguns dos meus scripts, acho-os relativamente esparsos e muitos podem ser substituídos por aspas duplas.
Chris FA Johnson
A escolha de aspas simples ou duplas dificilmente deve ser influenciada por algo tão trivial e irrelevante quanto a questão de saber se o texto do seu script é uma sequência válida de aspas simples. Aspas simples são usadas para evitar expansões, enquanto as aspas duplas permitem determinadas expansões e requerem análise extra. Este é o critério real para determinar qual usar.
Jw013 11/07
Esta é de longe a maneira mais chique de fazê-lo. Ótimo para pequenos blocos de documentação. Eu gosto mais do que /* */isso, não me deixe começar <!-- -->!
Alex cinzento
1

Se seu comentário estiver no final do script, você poderá fazer o seguinte:

#!/bin/sh
echo 'hello world'
exec true
we can put whatever we want here
\'\"\$\`!#%&()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_
abcdefghijklmnopqrstuvwxyz{|}~
Steven Penny
fonte