Comentando em um script Bash dentro de um comando de múltiplas linhas

164

Como posso comentar em cada linha das seguintes linhas de um script?

cat ${MYSQLDUMP} | \
sed '1d' | \
tr ",;" "\n" | \
sed -e 's/[asbi]:[0-9]*[:]*//g' -e '/^[{}]/d' -e 's/""//g' -e '/^"{/d' | \
sed -n -e '/^"/p' -e '/^print_value$/,/^option_id$/p' | \
sed -e '/^option_id/d' -e '/^print_value/d' -e 's/^"\(.*\)"$/\1/' | \
tr "\n" "," | \
sed -e 's/,\([0-9]*-[0-9]*-[0-9]*\)/\n\1/g' -e 's/,$//' | \
sed -e 's/^/"/g' -e 's/$/"/g' -e 's/,/","/g' >> ${CSV}

Se eu tentar adicionar um comentário como:

cat ${MYSQLDUMP} | \ # Output MYSQLDUMP File

Eu recebo:

#: not found

É possível comentar aqui?

BassKozz
fonte
1
Bem, como você notou, se você fizer # primeiro, então \ se tornará apenas parte do comentário, mas se você fizer primeiro, os caracteres posteriores na linha mudarão seu significado de "continuação de linha" para "citação". Eu pensei em uma solução, dada abaixo.
DigitalRoss

Respostas:

203

Isso terá alguma sobrecarga, mas tecnicamente ele responde à sua pergunta:

echo abc `#Put your comment here` \
     def `#Another chance for a comment` \
     xyz, etc.

E para tubulações especificamente, há uma solução limpa sem custos indiretos:

echo abc |        # Normal comment OK here
     tr a-z A-Z | # Another normal comment OK here
     sort |       # The pipelines are automatically continued
     uniq         # Final comment

Consulte a pergunta Estouro de pilha Como colocar um comentário de linha para um comando de várias linhas .

DigitalRoss
fonte
1
Parece bastante complexo, se não houver um método mais simples?
BassKozz 21/09/09
1
Ok, eu adicionei uma variação um pouco mais simples.
DigitalRoss
1
Você pode modificar sua resposta apenas para mostrar o fato de que a barra invertida não é necessária para que eu possa colocar os comentários ao lado de cada linha e usar apenas um cano?
BassKozz 21/09/09
Eu verifiquei que as versões um e dois funcionam. No entanto, você pode explicar por que eles fazem e o que está acontecendo aqui? Obrigado.
Faheem Mitha
1
Obrigada pelo esclarecimento. Eu abri uma pergunta no unix.sx pedindo mais detalhes, bash multi line command com comentários após o caractere de continuação .
Faheem Mitha
39

A barra invertida à direita deve ser o último caractere na linha para ser interpretada como um comando de continuação. Nenhum comentário ou mesmo espaço em branco é permitido depois dele.

Você deve poder colocar linhas de comentário entre seus comandos

# output MYSQLDUMP file
cat ${MYSQLDUMP} | \
# simplify the line
sed '/created_at/d' | \
# create some newlines
tr ",;" "\n" | \
# use some sed magic
sed -e 's/[asbi]:[0-9]*[:]*//g' -e '/^[{}]/d' -e 's/""//g' -e '/^"{/d' | \
# more magic
sed -n -e '/^"/p' -e '/^print_value$/,/^option_id$/p' | \
# even more magic
sed -e '/^option_id/d' -e '/^print_value/d' -e 's/^"\(.*\)"$/\1/' | \
tr "\n" "," | \
# I hate phone numbers in my output
sed -e 's/,\([0-9]*-[0-9]*-[0-9]*\)/\n\1/g' -e 's/,$//' | \ 
# one more sed call and then send it to the CSV file
sed -e 's/^/"/g' -e 's/$/"/g' -e 's/,/","/g' >> ${CSV}
multidão
fonte
12
\ Não é necessário quando o componente de comando do pipeline termina com |
DigitalRoss
2
DigitalRoss, você está correto, posso apenas usar o pipe e não a barra invertida e, em seguida, meus # comentários funcionarão perfeitamente ... você pode postar isso como resposta para que eu possa aceitá-lo.
BassKozz 21/09/09
8
"Você deve poder colocar linhas de comentário entre seus comandos": não, isso só está funcionando porque o último caractere interpretado das linhas anteriores é |. Se você tentar cat file1\<newline>#comment<newline>file2, verá que não consegue cat file1 file2, mas sim cat file1; file2.
dubiousjim
5
No entanto, como outros já mencionaram, cat file1 | # comment<newline>sortfunciona bem. O mesmo acontece cat file1 && # comment<newline>echo foo. Portanto, os comentários podem ser incluídos após |ou &&ou ||, mas não após `\` ou no meio de um comando.
precisa saber é o seguinte
7

Como o DigitalRoss apontou, a barra invertida à direita não é necessária quando a linha termina |. E você pode colocar comentários em uma linha após um |:

 cat ${MYSQLDUMP} |         # Output MYSQLDUMP file
 sed '1d' |                 # skip the top line
 tr ",;" "\n" | 
 sed -e 's/[asbi]:[0-9]*[:]*//g' -e '/^[{}]/d' -e 's/""//g' -e '/^"{/d' |
 sed -n -e '/^"/p' -e '/^print_value$/,/^option_id$/p' |
 sed -e '/^option_id/d' -e '/^print_value/d' -e 's/^"\(.*\)"$/\1/' |
 tr "\n" "," |
 sed -e 's/,\([0-9]*-[0-9]*-[0-9]*\)/\n\1/g' -e 's/,$//' |   # hate phone numbers
 sed -e 's/^/"/g' -e 's/$/"/g' -e 's/,/","/g' >> ${CSV}
multidão
fonte
5

A barra invertida escapa o #, interpretando-o como seu caractere literal em vez de um caractere de comentário.

tobiasvl
fonte
3

$IFS comentar hacks

Esse hack usa a expansão de parâmetro on $IFS, que é usada para separar palavras em comandos:

$ echo foo${IFS}bar
foo bar

Similarmente:

$ echo foo${IFS#comment}bar
foo bar

Usando isso, você pode colocar um comentário em uma linha de comando com contination:

$ echo foo${IFS# Comment here} \
> bar
foo bar

mas o comentário precisará ser anterior à \continuação.

Observe que a expansão do parâmetro é realizada dentro do comentário:

$ ls file
ls: cannot access 'file': No such file or directory
$ echo foo${IFS# This command will create file: $(touch file)}bar
foo bar
$ ls file
file

Exceção rara

O único caso raro em que isso falha é se $IFSiniciado anteriormente com o texto exato que é removido via expansão (ou seja, após o #caractere):

$ IFS=x
$ echo foo${IFS#y}bar
foo bar
$ echo foo${IFS#x}bar
foobar

Observe que a final foobarnão tem espaço, ilustrando o problema.

Como $IFScontém apenas espaço em branco por padrão, é extremamente improvável que você encontre esse problema.


Crédito para comentário de @ PJH que desencadeou esta resposta.

Tom Hale
fonte
1

Além dos exemplos da DigitalRoss, aqui está outro formulário que você pode usar, se preferir, em $()vez de backticks`

echo abc $(: comment) \
     def $(: comment) \
     xyz

Obviamente, você também pode usar a sintaxe do cólon com backticks:

echo abc `: comment` \
     def `: comment` \
     xyz

Notas Adicionais

A razão $(#comment)não funciona é porque uma vez que ele vê o #, trata o resto da linha como comentários, incluindo os parênteses de fechamento: comment). Portanto, os parênteses nunca são fechados.

Os backticks são analisados ​​de maneira diferente e detectam o backtick de fechamento mesmo após a #.

wisbucky
fonte
1
Isso criará um novo shell para cada comentário?
Lonix #
0

Aqui está um script bash que combina as idéias e idiomas de vários comentários anteriores para fornecer, com exemplos, comentários embutidos com a forma geral ${__+ <comment text>}.

Em particular

  • <comment text> pode ser multi-linha
  • <comment text> não é expandido por parâmetro
  • nenhum subprocesso é gerado (portanto, os comentários são eficientes)

Há uma restrição sobre <comment text>, a saber, chaves '}'e parênteses desequilibrados ')'devem ser protegidos (ou seja, '\}'e '\)').

Há um requisito no ambiente local do bash:

  • o nome do parâmetro __deve estar desmarcado

Qualquer outro nome de parâmetro bash sintaticamente válido servirá no lugar de __ , desde que o nome não tenha um valor definido.

Um script de exemplo segue

# provide bash inline comments having the form
#     <code> ${__+ <comment>} <code> 
#     <code> ${__+ <multiline
#                   comment>} <code>

# utility routines that obviate "useless use of cat"
function bashcat { printf '%s\n' "$(</dev/stdin)"; }
function scat { 1>&2 bashcat; exit 1; }

# ensure that '__' is unset && remains unset
[[ -z ${__+x} ]] &&  # if '__' is unset
  declare -r __ ||   # then ensure that '__' remains unset 
  scat <<EOF         # else exit with an error
Error: the parameter __='${__}' is set, hence the
  comment-idiom '\${__+ <comment text>}' will fail
EOF

${__+ (example of inline comments)
------------------------------------------------
the following inline comment-idiom is supported
    <code> ${__+ <comment>} <code> 
    <code> ${__+ <multiline
                  comment>} <code> 
(advisory) the parameter '__' must NOT be set;
  even the null declaration __='' will fail
(advisory) protect unbalanced delimiters \} and \) 
(advisory) NO parameter-expansion of <comment> 
(advisory) NO subprocesses are spawned
(advisory) a functionally equivalent idiom is 
    <code> `# <comment>` <code> 
    <code> `# <multiline
               comment>` <code>
however each comment spawns a bash subprocess
that inelegantly requires ~1ms of computation 
------------------------------------------------}
John Sidles
fonte