What I see so far from this discussion: Ted has written a lot of useful
scripts, but they are explicitly for one shell (bash) on one kernel
(linux). I.e. portability is not a concern.
People immediately pointed out how easy it is to write non-portable shell
scripts, and others commented that it does not matter (to them).
Kernel portability matters to me. So does code that works without regard to
the shell someone is using. So does robust error handling. So does math.
These are all things that, in my experience, rule against complex shell
scripts.
I still prefer Go as my scripting language, but we all have our
preferences. And, yes, Go gets wordy, but it's a price I'm happy to pay for
good error handling. I much prefer an error message to 100 lines of python
backtrace.
On Wed, Jan 4, 2023 at 8:17 AM Dan Cross <crossd(a)gmail.com> wrote:
On Tue, Jan 3, 2023 at 11:16 PM Bakul Shah
<bakul(a)iitbombay.org> wrote:
On Jan 3, 2023, at 7:31 PM, Dan Cross
<crossd(a)gmail.com> wrote:
> On Tue, Jan 3, 2023 at 10:22 PM John Cowan <cowan(a)ccil.org> wrote:
>> Making shell scripts portable means not using pipelines, because
given
"foo | bar", kshNN and zsh execute foo in a subshell and bar in the
top-level shell, whereas in other shells, both foo and bar execute in
subshells. (For this reason, Posix allows either behavior.) Not having
pipelines is a pretty drastic limitation.
This came up at work just the other day:
echo ' hi ' | sed 's/^ *//;s/ *$//' | read bummer
echo $bummer
The behavior varies between ksh, zsh, bash, sh. Yay.
On this example sh, zsh, bash behave the same way on
freebsd. Rather than ban |, I think the lesson is to
*avoid* builtin commands in a pipeline that can affect
shell's environment. I only write /bin/sh scripts in
any case.
Interesting. In my testing, `bash` was the odd man out:
: doctor; zsh
: doctor; echo ' hi ' | sed 's/^ *//;s/ *$//' | read bummer
echo $bummer
hi
: doctor;
: doctor; bash
: doctor; echo ' hi ' | sed 's/^ *//;s/ *$//' | read bummer
echo $bummer
: doctor;
exit
: doctor; ksh
: doctor; echo ' hi ' | sed 's/^ *//;s/ *$//' | read bummer
: doctor; echo $bummer
hi
: doctor;
: doctor; sh
: doctor; echo ' hi ' | sed 's/^ *//;s/ *$//' | read bummer
: doctor; echo $bummer
hi
: doctor;
: doctor;
That's on illumos.
On OpenBSD, neither bash, ksh, or sh produce output, while zsh does. I
suspect ksh is pdksh and sh is a link to ksh there, though. ksh93
gives "hi".
On FreeBSD, neither bash nor sh produce "hi", but zsh and ksh93 do.
Same on DragonFly, macOS and Arch Linux. On 7th edition, I only tried
sh; empty output. 4.3BSD gives empty output for /bin/sh. For kicks,
neither tcsh nor csh understand `read`; I don't think that *csh has a
read-like builtin.
This is, of course, a silly example. Most script authors would do
something like:
bummer=`echo ' hi ' | sed 's/^ *//;s/ *$//'`
Or, perhaps even:
bummer=$(echo ' hi ' | sed 's/^ *//;s/ *$//')
Life's too short and at this point I prefer the latter, but more often
than not my fingers are wired for the former.
It is really unfortunate that infix | is so
beguiling!
Except for that a Lisp or Scheme based shell would've
been fine and dandy! :-)/2
Whatever happened to `es` ? I guess it died on the vine. It seemed
like a nifty idea.
I made a concerted effort to use `rc` as my shell on Unix for a little
while. Without all the supporting plan9 machinery, though, I gave up.
Minimalism is great in an environment that can augment it with useful
functionality; outside of that environment, it can be kind of a pain
for work-a-day use.
- Dan C.