Hats off to the author! I've long been a proponent of the colon command due to its no-op properties, but this just takes it to another level. One would definitely have to provide add comments to the ":" function as there seems to a good amount of esoterica contained within.
Hey, thanks for taking the time to read and commenting! :)
Problem #1 (at least for the "advanced" part of the article's suggestion) is unfixable unless you boil the ocean and change the POSIX spec. I tried to make that clear in the prose, but might have failed at it. It's also the reason why I chose the title to refer to `bash` scripts in particular.
Problem #2 becomes less relevant once you realize that problem #1 completely overshadows it. And in `zsh`, where you can also redefine `:` to invoke a custom function, tests via `[[` also work just like they do in bash.
How is the POSIX non compliance a major problem? Does it have practical impacts when writing scripts that are not meant to be portable to other systems/shells?
Unfortunately it doesn't work if you forbid unbound variables with set -u. Like this (as suggested in the Unofficial strict mode article: https://news.ycombinator.com/item?id=8054440):
$cat z
#!/bin/bash
set -u # fail if unset variable is used
if [[ -n ${COLODEBUG} && ${-} != *x* ]]
then
:() {
[[ ${1:--} != ::* ]] && return 0
printf '%s\n' "${*}" >&2
}
fi
echo hello
$./z
./z: line 10: COLODEBUG: unbound variable
$
You are right, this change makes the drop-in snippet more robust: If one issues `set -u` before trying or deciding whether to redefine `:` (which would also be the effect of invoking the interpreter with the `-u` option), the variant presented in the article breaks. If the shall-we-redefine-: check has already been performed before `-u` is in effect, the alternative implementation of `:` itself will work fine.
It's kinda unfortunate this slipped through, because before I tried to "formalize" this little trick in the article yesterday, I definitely remember having used variants that guarded against this little nasty trap you now independently rediscovered ;)
Would you mind me updating the article accordingly, and crediting your HN account name/profile in the changelog?
Thanks a lot for your rigorous reading and very constructive feedback! :)
16 comments
[ 4.6 ms ] story [ 47.4 ms ] threadmajor: it does not work on POSIX shells, because ':' is not a valid function name and
minor: the function itself should be changed to use the builtin 'case' instead of the bashims [[ ... ]]
Problem #1 (at least for the "advanced" part of the article's suggestion) is unfixable unless you boil the ocean and change the POSIX spec. I tried to make that clear in the prose, but might have failed at it. It's also the reason why I chose the title to refer to `bash` scripts in particular.
Problem #2 becomes less relevant once you realize that problem #1 completely overshadows it. And in `zsh`, where you can also redefine `:` to invoke a custom function, tests via `[[` also work just like they do in bash.
Would it be OK for you if I added that information/workaround to the article (crediting you, of course)?
Here's how I do the equivalent with a POSIX function to print a message to STDOUT:
It prompted me to mention BashSupport Pro which I installed a couple of months back.
It's a plugin for JetBrains IDEs that allows step debugging and variable inspection for Bash scripts in the same way as other supported languages.
https://www.bashsupport.com/
It's kinda unfortunate this slipped through, because before I tried to "formalize" this little trick in the article yesterday, I definitely remember having used variants that guarded against this little nasty trap you now independently rediscovered ;)
Would you mind me updating the article accordingly, and crediting your HN account name/profile in the changelog?
Thanks a lot for your rigorous reading and very constructive feedback! :)
No problem. I'm retired now so my name doesn't appear in changelogs as often as it used to!
The first suggestion is to add
just before the fi so that it is available to scripts called from the main script.The second is to add
before the printf.because if I didn't then each word of the comment would appear on a separate line like this:
instead of this: the reason for this is that I had defined as suggested by the Unofficial Strict Mode.