Are those really POSIX or just bash? Namely the $() example. I was under the impression that only `` was POSIX, and that $() was bash/zsh-specific (maybe ksh too).
Also,
${CC:=gcc}
is only more readable than:
[ -z "$CC" ] || CC=gcc
if you know what that syntax means. There are a ton of syntax in bash/zsh to modify varables inside of the ${} construct. I usually have to look them up every time that I see them, even when I was the one the wrote the original code. I would say that more people know the 'test' syntax than the ${:=} syntax.
> 3. You can assign one variable to another without quoting
This is somewhat annoying, because something like this:
command="ls -l"
$command /path/to/dir
doesn't work. It tries to run a command called "ls -l" which probably doesn't exist. Passing that to exec will work, though. A more common example of this issue would be trying to build a command-line in the shell script before executing it, you might have base level of options:
$() is standard, not a bashism. Every code example in the article was tested on multiple shells. Use $() and be happy, and I recommend never touching the backquotes again. They're a disaster as soon as you need to nest them.
${CC:=gcc} is a special case of syntax, but one of the points in the article is: as with any programming language, you should actually learn it so you can write better code. If people start using this one, it won't be any lesser known than any other weird sh syntax. The other variants (=, -, :-, etc) the article recommends against anyway.
As for your comments on #3, both of your examples are untrue; they work fine in a POSIX shell. Try it. (They fail in zsh, when zsh isn't in "sh compatibility" mode, so perhaps you're using that. Try switching it to sh compatibility mode.) Either way, those examples aren't actually related to point #3 in the article.
> Use $() and be happy, and I recommend never touching
> the backquotes again.
Any clue why the 'sh' filetype in Vim highlights $() as an error unless it reads "#!/bin/bash" on the first line of the file? (Zsh actually has its own filetype, but unfortunately no folding built-in support like the sh filetype) There's gotta be a reasoning behind that. Maybe $() isn't POSIX, but unofficially standard b/c most shells support it?
[ Note (IIRC) in vim shell filetypes are like this: sh=(sh, bash, ksh) zsh=(zsh) csh=(csh, tcsh) ]
> Either way, those examples aren't actually related to point
> #3 in the article.
They were sort of related in that I was talking about the shell implicitly quoting the contents of the variable. I was just pointing out a different context where (I believe) that it also does something similar.
> They fail in zsh, when zsh isn't in "sh compatibility" mode,
> so perhaps you're using that.
I ran into issues with that a few years ago, and then steered clear of using things in that way. I may well have been using zsh at the time as I was using it for a while before switching to bash, and then back again to zsh (and I didn't keep notes on that timeline).
I think it would be nifty if every title linked to the relevant section of the POSIX spec (maybe with a [POSIX] link next to the title itself).
Also, OpenBSD's pdksh seems to stick quite closely to POSIX shell features, it's probably a good test environment.
> In general, beware of trusting the people who wrote your editor instead just trying it to see if it works :)
That runs the risk of encountering an additional feature of the current shell compared to POSIX, this is very much the source of all bashisms: just trying to see if it works.
pdksh (at least the one in Debian) has numerous bugs; try the shelltest.od script in redo to see some of them.
I agree that "just see if it works" isn't a good portability strategy if you only test one shell. But the idea is to get as many shells as possible and try them all, or (as redo does) to write a script that accepts only shells with all the expected features. Blindly assuming POSIX compliance is a dangerous way to go, since there's no guarantee that it's in a shell just because it's in the spec.
I'll grant you that using a feature that's both in POSIX and in all the shells you test is the best option, though :) $() is in both categories.
I'm not 'relying' on Vim, I'm just wondering. I got the impression that backticks were the only POSIX-approved way outside of Vim, but Vim highlighting it as such did help to re-enforce that idea (along with the exclusive usage of backticks in other people's code that was attempting to be strictly POSIX-compliant).
I didn't meant to come across as critical. That's a very reasonable conclusion to come to, and it's the reason why it's such a shame that vim upstream don't want to highlight #!/bin/sh scripts as POSIX syntax by default.
contrast this with emacs' syntax highlighting, that tends to break badly on any non-trivial use of backquotes. That actually shows the advantage of $() - it is simply easier to scan, both for highlighters and human readers.
That said, there are many shells, that don't support $() and other random POSIX shell features. In fact, assuming that POSIX = portable is asking for trouble, because most systems actually aren't entirely conforming to POSIX (even when they are certified as being so). Another problem with relying on POSIX for portability is that in some places, the specification is worded in way that suggest one meaning and actually means something else (see for example behavior of glibc when operating on already terminated threads, which is POSIX compliant, but that this is correct is not immediately obvious from the specification).
I'm pretty sure Solaris is one of those nasty OSes that continues to include a broken /bin/sh for "backwards compatibility." They presumably also have a non-broken shell around somewhere in the standard install. This is why redo goes through extra effort to choose a non-broken shell for running your .do scripts.
Solaris has a POSIX shell in /usr/xpg4/bin/sh. Unfortunately, there is no way to make /bin/sh POSIX-compliant, e.g. by setting an environment variable, a feature many other Unixes have.
Also,
is only more readable than: if you know what that syntax means. There are a ton of syntax in bash/zsh to modify varables inside of the ${} construct. I usually have to look them up every time that I see them, even when I was the one the wrote the original code. I would say that more people know the 'test' syntax than the ${:=} syntax. This is somewhat annoying, because something like this: doesn't work. It tries to run a command called "ls -l" which probably doesn't exist. Passing that to exec will work, though. A more common example of this issue would be trying to build a command-line in the shell script before executing it, you might have base level of options: But $base_options gets passed as a single parameter to command.