Commentare in uno script Bash all'interno di un comando multilinea


165

Come posso commentare ogni riga delle seguenti righe da uno 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 provo ad aggiungere un commento come:

cat ${MYSQLDUMP} | \ # Output MYSQLDUMP File

Ottengo:

#: not found

È possibile commentare qui?


1
Bene, come hai notato, se fai prima #, allora \ diventa solo una parte del commento, ma se lo fai \ first, i caratteri successivi sulla riga cambiano il loro significato da "continuazione di riga" a "virgolette". Ho pensato a una soluzione, data di seguito.
DigitalRoss,

1
possibile duplicato di Come
inserire

Risposte:


204

Questo avrà un certo sovraccarico, ma tecnicamente risponde alla tua domanda:

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

E per le pipeline in particolare, esiste una soluzione pulita senza spese generali:

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

Vedi la domanda Stack Overflow Come inserire un commento di riga per un comando multilinea .


1
Sembra piuttosto complesso, se non ci fosse un metodo più semplice?
BassKozz,

1
Ok, ho aggiunto una variazione leggermente più semplice.
DigitalRoss,

1
Puoi modificare la tua risposta solo per mostrare il fatto che la barra rovesciata non è necessaria in modo che io possa mettere i commenti accanto a ciascuna riga e usare solo una pipe?
BassKozz,

Ho verificato che le versioni 1 e 2 funzionino. Tuttavia, puoi spiegare perché lo fanno e cosa sta succedendo qui? Grazie.
Faheem Mitha,

1
Grazie per la spiegazione. Ho aperto una domanda su unix.sx chiedendo maggiori dettagli, bash comando multi linea con commenti dopo il carattere di continuazione .
Faheem Mitha,

39

La barra rovesciata finale deve essere l'ultimo carattere sulla riga affinché possa essere interpretato come un comando di continuazione. Non sono ammessi commenti o spazi bianchi dopo di esso.

Dovresti essere in grado di inserire righe di commento tra i tuoi comandi

# 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}

12
\ Non è necessario quando il componente del comando pipeline termina con |
DigitalRoss,

2
DigitalRoss, hai ragione, posso solo usare la pipe e non la barra rovesciata e quindi i miei #commenti funzioneranno perfettamente ... puoi pubblicarlo come risposta in modo che io possa accettarlo.
BassKozz,

8
"Dovresti essere in grado di inserire delle righe di commento tra i tuoi comandi": no, funziona solo perché l'ultimo carattere interpretato delle righe precedenti è |. Se ci provi cat file1\<newline>#comment<newline>file2, vedrai che non ottieni cat file1 file2, ma piuttosto cat file1; file2.
dubiousjim,

5
Tuttavia, come altri hanno già detto, cat file1 | # comment<newline>sortfunziona benissimo. Lo stesso vale cat file1 && # comment<newline>echo foo. Quindi i commenti possono essere inclusi dopo |o &&o ||, ma non dopo `\` o nel mezzo di un comando.
dubiousjim,

7

Come ha sottolineato DigitalRoss, la barra rovesciata finale non è necessaria quando termina la linea |. E puoi inserire commenti su una riga che segue a |:

 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}

5

La barra rovesciata sfugge al #, interpretandolo come carattere letterale anziché come carattere di commento.


3

$IFS hack di commenti

Questo hack utilizza l' espansione dei parametri su $IFS, che viene utilizzata per separare le parole nei comandi:

$ echo foo${IFS}bar
foo bar

Allo stesso modo:

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

Usando questo, puoi inserire un commento su una riga di comando con contination:

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

ma il commento dovrà essere prima della \continuazione.

Si noti che l'espansione dei parametri viene eseguita all'interno del commento:

$ 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

Eccezione rara

L'unico caso raro che ciò fallisca è se $IFSprecedentemente avviato con il testo esatto che viene rimosso tramite l'espansione (ovvero, dopo il #carattere):

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

Nota che il finale foobarnon ha spazio, illustrando il problema.

Poiché $IFScontiene solo spazi bianchi per impostazione predefinita, è estremamente improbabile che si verifichi questo problema.


Ringraziamo il commento di @ pjh che ha scatenato questa risposta.


1

Oltre agli esempi di DigitalRoss, ecco un altro modulo che puoi usare se preferisci $()invece di backtick`

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

Ovviamente, puoi usare la sintassi dei due punti anche con i backtick:

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

Note aggiuntive

Il motivo $(#comment)non funziona perché una volta che vede il #, tratta il resto della riga come commenti, comprese le parentesi quadre:comment) . Quindi le parentesi non sono mai chiuse.

I backtick analizzano diversamente e rileveranno il backtick di chiusura anche dopo a #.


1
Ciò creerà una nuova shell per ogni commento?
Lonix,

0

Ecco uno script bash che combina le idee e gli idiomi di diversi commenti precedenti per fornire, con esempi, commenti incorporati che hanno la forma generale ${__+ <comment text>} .

In particolare

  • <comment text> può essere multilinea
  • <comment text> non è espanso da parametri
  • non vengono generati sottoprocessi (quindi i commenti sono efficienti)

Esiste una limitazione per quanto riguarda <comment text>, cioè, parentesi graffe sbilanciate '}'e parentesi ')'devono essere protette (vale a dire, '\}'e'\)' ).

C'è un requisito nell'ambiente bash locale:

  • il nome del parametro __deve essere non impostato

Qualsiasi altro nome-parametro bash sintatticamente valido servirà al posto di __ , a condizione che il nome non abbia un valore impostato.

Segue uno script di esempio

# 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 
------------------------------------------------}
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.