Bash – Readable comments on separate lines in a multi-line bash command with pipelines

bashpipeshell

When creating shell scripts using pipelines, and using the backslash to continue lines, I want to insert comments on separate lines, in a robust, readable and portable fashion.

For example, given this uncommented multi-line command (stolen from @DigitalRoss for its clarity):

echo abc |
     tr a-z A-Z |
     sort |
     uniq

… the below is aesthetically closest to what I want to accomplish, but for obvious reasons, does not work … and yes, I'm well aware that this isn't something normally worth commenting:

# Perform critical system task.
# NOTE - An example of what does *not* work.
echo abc |
    # Convert lowercase to uppercase.
     tr a-z A-Z |

     # Sort the results.
     sort |

     # Only show unique lines.
     uniq

Existing related answers appear unsatisfactory for me, as follows:

First, glenn jackman's answer (adding arguments to an array, and then executing the array) works for single commands, but does not work for pipelining (and even if it did, it adds complexity that I would like to avoid).

Second, @Gilles' answer here (which uses :) also doesn't appear to work with pipelining, because it alters the flow of the pipeline:

$ echo "abc" | :
$

(NOTE: If there is an equivalent to : that passes output unmodified, that would be aesthetically acceptable, but I haven't been able to find one. I could write a custom one, but it would reduce portability.)

Finally, the last part of DigitalRoss' answer on StackOverflow works well for adding comments on the same line, but I strongly prefer comments on separate lines. Otherwise, when lines have widely varying lengths, readability is reduced:

echo abc |         # normal comment OK here`
     /usr/local/bin/really/long/path/ridiculously-long-filename.sh |  # another normal comment OK here
     sort |        # the pipelines are automatically continued
     uniq          # final comment

I'm looking for answers that preserve readability and minimize complexity, or else some background on why what I'm looking for is infeasible.

Best Answer

How about this?

echo abc | \
# Convert lowercase to uppercase.
tr a-z A-Z | \

# Sort the results.
sort | \

# Only show unique lines.
uniq

(The backslash needs to be used as the last character in those lines.) I'm not sure about the portability of that approach, but it sure works with current bash.