Commenting in a Bash script inside a multiline command

328,311

Solution 1

This will have some overhead, but technically it does answer your question:

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

And for pipelines specifically, there is a clean solution with no overhead:

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

See Stack Overflow question How to Put Line Comment for a Multi-line Command.

Solution 2

The trailing backslash must be the last character on the line for it to be interpreted as a continuation command. No comments or even whitespace are allowed after it.

You should be able to put comment lines in between your commands

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

Solution 3

As DigitalRoss pointed out, the trailing backslash is not necessary when the line woud end in |. And you can put comments on a line following 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}

Solution 4

$IFS comment hacks

This hack uses parameter expansion on $IFS, which is used to separate words in commands:

$ echo foo${IFS}bar
foo bar

Similarly:

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

Using this, you can put a comment on a command line with contination:

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

but the comment will need to be before the \ continuation.

Note that parameter expansion is performed inside the comment:

$ 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

Rare exception

The only rare case this fails is if $IFS previously started with the exact text which is removed via the expansion (ie, after the # character):

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

Note the final foobar has no space, illustrating the issue.

Since $IFS contains only whitespace by default, it's extremely unlikely you'll run into this problem.


Credit to @pjh's comment which sparked off this answer.

Solution 5

The backslash escapes the #, interpreting it as its literal character instead of a comment character.

Share:
328,311

Related videos on Youtube

BassKozz
Author by

BassKozz

About Me

Updated on April 19, 2022

Comments

  • BassKozz
    BassKozz about 2 years

    How can I comment on each line of the following lines from a 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}
    

    If I try and add a comment like:

    cat ${MYSQLDUMP} | \ # Output MYSQLDUMP File
    

    I get:

    #: not found
    

    Is it possible to comment here?

    • DigitalRoss
      DigitalRoss over 14 years
      Well, as you noticed, if you do # first, then the \ becomes just part of the comment, but if you do \ first, then the later characters on the line change its meaning away from "line continuation" to "quote". I've thought of one solution, given below.
    • Braiam
      Braiam over 9 years
  • BassKozz
    BassKozz over 14 years
    Seems rather complex, if there no simpler method?
  • DigitalRoss
    DigitalRoss over 14 years
    Ok, I've added a slightly simpler variation.
  • DigitalRoss
    DigitalRoss over 14 years
    The \ is not necessary when the pipeline command component ends with |
  • BassKozz
    BassKozz over 14 years
    DigitalRoss, You are correct, I can just use the pipe and not the backslash and then my #comments will work perfectly... can you post that as an answer so I can accept it.
  • BassKozz
    BassKozz over 14 years
    Can you modify your answer just to show the fact that the backslash is not needed so I can put the comments next to each line and just use a pipe?
  • Faheem Mitha
    Faheem Mitha over 12 years
    I verified that versions one and two work. However, can you explain why they do and what is going on here? Thanks.
  • DigitalRoss
    DigitalRoss over 12 years
    There used to be a shell goto command which branched to labels specified like : here. The goto is gone but you can still use the : whatever syntax ... : is a sort of parsed comment now.
  • Faheem Mitha
    Faheem Mitha over 12 years
    Thanks for the explanation. I've opened a question on unix.sx asking for more details, bash multi line command with comments after the continuation character.
  • dubiousjim
    dubiousjim over 11 years
    "You should be able to put comment lines in between your commands": no, this is only working because the last interpreted character of the previous lines is |. If you try cat file1\<newline>#comment<newline>file2, you'll see you don't get cat file1 file2, but rather cat file1; file2.
  • dubiousjim
    dubiousjim over 11 years
    However, as others have mentioned, cat file1 | # comment<newline>sort works fine. So too does cat file1 && # comment<newline>echo foo. So comments can be included after | or && or ||, but not after `\` or in the middle of a command.
  • Don Hatch
    Don Hatch over 7 years
    The "for pipelines specifically" method is superficially nice, but it has a very annoying drawback: if I copy-paste your example into an interactive bash shell, it works great... but then if I then type !! or up-arrow to re-execute the command, it gets mangled. Your first suggestion seems to be more robust.
  • lonix
    lonix over 4 years
    Will that create a new shell for every comment?
  • Jim Grisham
    Jim Grisham about 3 years
    Doesn't that work even removing your list elements?
  • xebeche
    xebeche about 3 years
    @JimGrisham Yes, thanks for pointing this out. I've changed my answer accordingly. Now, technically, it's identical to other answers but strangely, so far, nobody else had shown code with leading pipes.
  • Mehrad Mahmoudian
    Mehrad Mahmoudian over 2 years
    Just for transparency as my changes are not peer-reviewed: The original post has ${__+ and it produced some error for me and after some searching I realized it should comply with ${name:+word} format to work and hence I changed it to ${__:+. For more info check out zsh.sourceforge.io/Doc/Release/Expansion.html and gnu.org/software/bash/manual/html_node/…