3

How can I comment a list of arguments to a function? I'd like to do something like this, which does not work:

my_func \
  # This is for something
  arg_1 \
  \
  # This is for something else
  arg_2 \
  \
  # This is not not for anything
  arg_3

Which obviously doesn't work. Is there any way to achieve something like this? The next option would be something like this:

my_func \
  arg_1 \ # This is for something
  arg_2 \ # This is for something else
  arg_3 # This is not not for anything

Which is less desirable in my book but also does not work. Any ideas?

ACK_stoverflow
  • 3,148
  • 4
  • 24
  • 32
  • I think people usually comment the function itself and perhaps print a detailed usage with `--help` or when the function is called with no arguments. – karakfa Mar 17 '16 at 13:34
  • @karakfa It's a function not a script. And the function has a comment, what I need to comment are the args - why I passed this and that to the function. – ACK_stoverflow Mar 17 '16 at 13:36

3 Answers3

3

Using command substitution as a fake comment is both expensive (you still have to fork a shell and parse the comment) and possibly dangerous (command substitutions can be nested, and those will still be executed). A better way is to store your arguments in an array where there is no chance of inadvertent execution.

args=(
      # This is for something
      arg_1

      # This is for something else
      arg_2

      # This is not not for anything
      arg_3
)

my_func "${args[@]}"

If you need to remain POSIX-compliant, meaning no arrays, I suggest simply documenting the arguments prior to the call:

# Arg 1: this is for something
# Arg 2: this is for something else
# Arg 3: this is not for anything
my_func \
  arg_1 \
  arg_2 \
  arg_3
chepner
  • 497,756
  • 71
  • 530
  • 681
  • Thanks for providing more options. Unfortunately, our style convention prohibits bash arrays, and the actual number of arguments to the function is much more than 3, making your second proposal less than desirable. – ACK_stoverflow Mar 17 '16 at 14:28
  • Arrays are extremely useful in Bash programs, and they have been supported since version 2.0 (1997). A style convention that prohibits their use is a very bad idea. If portable shell code is required, it would be helpful to remove the 'bash' tag from the question. – pjh Mar 17 '16 at 19:35
  • We're a tiny team, but the idea is "if you need real data structures, use python", which I'm a big fan of. – ACK_stoverflow Mar 17 '16 at 20:09
  • Banning useful Bash features may have the unintended consequence of causing people to write unnecessarily bad Bash code, or spend a lot of time unnecessarily translating Bash code to Python. A more useful style convention rule would be one that advises against having large numbers of (positional) function arguments. Limitations of Bash functions often mean that you either need to have excessive numbers of function arguments or use global variables to pass data to functions. Those are strong signs that Python might be a more appropriate language for the program. – pjh Mar 22 '16 at 20:14
1

This works, and has minimal impact on performance, but it is not pretty:

my_func \
    ${IFS# This is for something } \
    arg_1 \
    \
    ${IFS# This is for something else } \
    arg_2 \
    \
    ${IFS# This is not not for anything } \
    arg_3
pjh
  • 6,388
  • 2
  • 16
  • 17
-2

The question boils down to "how do I make an inline comment in bash", and the technically correct answer is that you cannot. However, you can approximate inline comments, as shown in this answer.

So the way to do it (not overhead-free, but it's the closest thing to what I wanted) is:

my_func \
  arg_1 `# This is for something` \
  arg_2 `# This is for something else` \
  arg_3 # This is not not for anything

Or

my_func \
  `# This is for something` \
  arg_1 \
  \
  `# This is for something else` \
  arg_2 \
  \
  `# This is not not for anything` \
  arg_3
Community
  • 1
  • 1
ACK_stoverflow
  • 3,148
  • 4
  • 24
  • 32
  • Why the downvotes? This solution totally works and is the same as the accepted answer on numerous other questions. – ACK_stoverflow Mar 17 '16 at 14:23
  • Whoever accepted those answers was as mistaken as you regarding whether this is a good idea. (And if you've seen this answer before, why are you posting a deliberate duplicate?) – chepner Mar 17 '16 at 14:27
  • I suppose it's "not a good idea" because it's technically expensive (you spawn a useless process for each comment). But I'd argue that it's more readable than other solutions and the performance overhead is negligible. If you had read my answer you would have seen the link, which answers the more general question of "how to make an inline comment in bash". The question itself is not duplicate. – ACK_stoverflow Mar 17 '16 at 14:35
  • @chepner So I tested my assumptions (http://pastebin.com/g5vYcAMv ). Using 1001 inline comments via command substitution took less than a quarter of a second on my machine: `real 0m0.216s user 0m0.028s sys 0m0.048s`. – ACK_stoverflow Mar 17 '16 at 15:48
  • Using 1001 inline comments via command substitution took over 44 seconds under Cygwin on my PC. (I did not downvote this answer though.) – pjh Mar 17 '16 at 18:56
  • @pjh Interesting. I wonder how cygwin emulates /dev/null. Can you try this paste instead? (http://pastebin.com/PcGS9f6A) By actually doing nothing in the function I shaved off a few hundredths of a second `real 0m0.208s user 0m0.020s sys 0m0.048s`. – ACK_stoverflow Mar 17 '16 at 20:13
  • @ACK_stoverflow, the minimum run time I got for the pastebin code was just over 46 seconds. The problem is that Bash always creates a subprocess for command substitution, creating a process is very expensive on Windows, and (I believe) Cygwin makes it even more expensive by emulating a `fork`. – pjh Mar 18 '16 at 11:01
  • @pjh Process substitution is not a good option on Cygwin or resource-constrained systems, got it. Thanks. – ACK_stoverflow Mar 18 '16 at 18:38