What goodies are present in UNIX shells sans BASH? - bash

I have been using 'bash' since the time I have been using Unix- Linux/Solaris. Now, I am interested to know what do shells like 'ksh','zsh' offer better? What do 'geeks' use?

I'm partial to zsh (it's like a blend of ksh and bash). The guide has a nice overview of its features. This page has a nice chart showing the availability of different features in different shells.

bash: In my experience, most people use bash, partly because it is the standard shell in most Linux systems.
ksh: Many Solaris systems use ksh instead, but that seems to be loosing popularity to bash.
csh: Csh used to be more popular, but was generally superseded by tcsh. tcsh is not bad for those who are very comfortable with c-like syntax.
zsh: I have not used zsh, but it seems to be very feature rich.
Personally, I prefer bash, because it is installed on almost every unix-compatible OS, it is very versatile, and is a good compromise between a simple command-line tool and a scripting language.

Bash is best to know for the most broad compatibility, you can sit at basically any Unix and it will be there.
Zsh is one of the most modern shells, probably. There's all kinds of crazy fun stuff you can do with it

I use ksh93 by preference. This means that the basics of ksh are available on pretty much any system I find myself on, so my interactive experience and 98% of my complex profile stay the same.

bash is a bit slow, but like many FSF programs, it tries to incorporate all known features. I use ksh93, which has largely converged with bash. The main advantage of ksh is that it's got a nice interface for extending the shell with C code. It's also a little easier to customize, e.g., to make tab key do whatever you want, in context. Disadvantage is that command completion is not built in; you have to program it.
Avoid csh and its derivatives :-)

In my experience, there are very few goodies in standard Unix shells (where that means, to me, csh, sh, ksh) that are not also present in at least an equivalent form in bash. Consequently, as long as you are comfortable that bash will be on all your machines, you may as well use it to get the maximum functionality.
OTOH, if you want to deal with portability, you will probably use ksh, which hews pretty close to the POSIX standard - with some extensions (bash is also fairly close to the POSIX standard, but with rather more extensions).
I really like the POSIX $(cmd) notation in place of the classic back-ticks
`cmd`
(That was not fun in Markdown!). One major reason for liking it is that it is much, much easier to nest the calls:
gcclib=$(dirname $(dirname $(which gcc)))/lib
Getting that right on one line with back-ticks is silly enough that you would not attempt to make it into a one-liner. That's in ksh and bash; it is not in the classic Bourne shell (/bin/sh, but be aware that /bin/sh on some machines is not the classic Bourne shell but bash in disguise), nor in the C shell.

If you're using bash and you're happy with it, no need to change right away. It's a good shell. Knowing the history of it tells you something about it too: Bourne Again SHell. It was a good attempt to make a better shell than the C-Shell and its derivatives (like tcsh), allowing you to use /bin/sh syntax for scripting (or for interactive use), but adding some of the nicer features of csh (like history and so on).
The Korn shell and Bash have a lot in common, in concept anyway. Like /bin/sh, the Korn shell came from AT&T originally, and wasn't open sourced until relatively recently. It has a good history mechanism, and does file locking on history state files so that if they're mounted on network file servers, multiple copies of the shell will properly write to the history file without clobbering each other. It also supports /bin/sh syntax, and incorporates some of the good things about /bin/csh. There's a lot to ksh, and it's generally a pretty good shell, if you can find it. I used to use it on Solaris, especially back when I was working at Sun. I didn't want to install anything that didn't come with the OS, since I installed a new OS several times a week, so this was a good choice.
Now I use either Bash or zsh. I prefer zsh because of its rich set of features for command completion and for writing shell functions in general (for my interactive shells -- when programming scripts, I stick to pretty standard Bourne shell stuff).
As others have said, it's best to avoid any version of the C-shell, except for those shells that give you some features of /bin/csh but aren't derived from /bin/csh code.

I had one rigged up to provide per-session shell history.
The unique thing here was each window had its own shell history. Quite convenient.

Related

KornShell or Bash Shell for ETL process?

I am working on a project where I need to load the data into data warehouse using ETL process. I have data in csv, unstructured and flat file format. I am thinking about using shell scripting to carry out the ETL process. I know little about both bash shell and KornShell (ksh) but I am very new in ETL process. So my question is what is the better option for ETL process. Whether I should use Bash Shell or KornShell?
The answer from user experienced with ETL process and shell scripting is highly appreciated.
Thank in advance.
Typically, my ETL processes use SQL statements to do in-database transformation, so they're really "ELT" process. The shell simply serves as the tool to move files around, execute data loads & extracts, and execute SQL statements. If your DW is on a sufficiently powerful system, it's usually the best place to do the transformation work, unless you are set on having a system living outside of the EDW that does data transformations.
The choice of shell for such an ELT process that I've described is really one of maintenance. Who will be supporting this when you're gone? Does the company have lots of folks who know bash, but only one that knows KSH? Or is it 99% a .NET shop? Then I'd suggest writing your ETL in little C# console apps. The choice of the language you use to execute your ETL, when you're not using a real "ETL" tool, should be focused on these factors, not on the 'best' language.
Korn is slightly more portable. Bash is a lot more powerful. "Bourne shell" is a good least common denominator.
All things being equal, I'd recommend "bash". Especially if your platform is Linux.
IMHO ..
PS:
The name "bash" stands for "Bourne Again Shell", a pun on its heritage from the original "Bourne" shell. Bourne scripts are bash-compatible, but not vice versa.

Is there a minimally POSIX.2 compliant shell?

Is there a minimally POSIX.2 compliant shell (let's call it mpcsh) in the following sense:
if mpcsh myscript.sh behaves correctly on my (compliant) system then xsh myscript.sh will behave identically for any POSIX.2 compliant shell xsh on any compliant system. ("Identically" up to less relevant things like the wording of error messages etc.)
Does dash qualify?
If not, is there any way to verify compliance of myscript.sh?
Edit (9 years later):
The accepted answer still stands, but have a look at this blog post and the checkbashisms command (source). Avoiding bashisms is not the same as writing a POSIX.2 compliant shell script, but it comes close.
The sad answer in advance
It won't help you (not as much and reliably as you would expect and want it to anyway).
Here is why.
One big problem that cannot be addressed by a virtual "POSIX shell" are things that are ambiguously worded or just not addressed in the standard, so that shells may implement things in different ways while still adhering to the standard.
Take these two examples regarding pipelines, the first of which is well known:
Example 1 - scoping
$ ksh -c 'printf "foo" | read s; echo "[${s}]"'
[foo]
$ bash -c 'printf "foo" | read s; echo "[${s}]"'
[]
ksh executes the last command of a pipe in the current shell, whereas bash executes all - including the last command - in a subshell. bash 4 introduced the lastpipe option which makes it behave like ksh:
$ bash -c 'shopt -s lastpipe; printf "foo" | read s; echo "[${s}]"'
[foo]
All of this is (debatably) according to the standard:
Additionally, each command of a multi-command pipeline is in a subshell environment; as an extension, however, any or all commands in a pipeline may be executed in the current environment.
I am not 100% certain on what they meant with extension, but based on other examples in the document it does not mean that the shell has to provide a way to switch between behavior but simply that it may, if it wishes so, implement things in this "extended way". Other people read this differently and argue about the ksh behavior being non-standards-compliant and I can see why. Not only is the wording unlucky, it is not a good idea to allow this in the first place.
In practice it doesn't really matter which behavior is correct since those are the """two big shells""" and people would think that if you don't use their extensions and only supposedly POSIX-compliant code that it will work in either, but the truth is that if you rely on one or the other behavior mentioned above your script can break in horrible ways.
Example 2 - redirection
This one I learnt about just a couple of days ago, see my answer here:
foo | bar 2>./qux | quux
Common sense and POLA tells me that when the next line of code is hit, both quux and bar should have finished running, meaning that the file ./qux is fully populated. Right? No.
POSIX states that
If the pipeline is not in the background (see Asynchronous Lists), the shell shall wait for the last command specified in the pipeline to complete, and may also wait for all commands to complete.)
May (!) wait for all commands to complete! WTH!
bash waits:
The shell waits for all commands in the pipeline to terminate before returning a value.
but ksh doesn't:
Each command, except possibly the last, is run as a separate process; the shell waits for the last command to terminate.
So if you use redirection inbetween a pipe, make sure you know what you are doing since this is treated differently and can horribly break on edge cases, depending on your code.
I could give another example not related to pipelines, but I hope these two suffice.
Conclusion
Having a standard is good, continuously revising it is even better and adhering to it is great. But if the standard fails due to ambiguity or permissiveness things can still unexpectedly break practically rendering the usefulness of the standard void.
What this means in practice is that on top of writing "POSIX-compliant" code you still need to think and know what you are doing to prevent certain things from happening.
All that being said, one shell which has not yet been mentioned is posh which is supposedly POSIX plus even fewer extensions than dash has, (primarily echo -n and the local keyword) according to its manpage:
BUGS
Any bugs in posh should be reported via the Debian BTS.
Legitimate bugs are inconsistencies between manpage and behavior,
and inconsistencies between behavior and Debian policy
(currently SUSv3 compliance with the following exceptions:
echo -n, binary -a and -o to test, local scoping).
YMMV.
Probably the closest thing to a canonical shell is ash which is maintained by The NetBSD Foundation, among other organizations.
A downstream variant of this shell called dash is better known.
Currently, there is no single role model for the POSIX shell.
Since the original Bourne shell, the POSIX shell has adopted a number of additional features.
All of the shells that I know that implement those features also have extensions that go beyond the feature set of the POSIX shell.
For instance, POSIX allows for arithmetic expressions in the format:
var=$(( expression ))
but it does not allow the equivalent:
(( var = expression ))
supported by bash and ksh93.
I know that bash has a set -o posix option, but that will not disable any extensions.
$ set -o posix
$ (( a = 1 + 1 ))
$ echo $a
2
To the best of my knowledge, ksh93 tries to conform to POSIX out of the box, but still allows extensions.
The POSIX developers spent years (not an exaggeration) wrestling with the question: "What does it mean for an application program to conform to the standard?" While the POSIX developers were able to define a conformance test suite for an implementation of the standards (POSIX.1 and POSIX.2), and could define the notion of a "strictly conforming application" as one which used no interface beyond the mandatory elements of the standard, they were unable to define a testing regime that would confirm that a particular application program was "strictly conforming" to POSIX.1, or that a shell script was "strictly conforming" to POSIX.2.
The original question seeks just that; a conformance test that verifies a script uses only elements of the standard which are fully specified. Alas, the standard is full of "weasel words" that loosen definitions of behavior, making such a test effectively impossible for a script of any significant level of usefulness. (This is true even setting aside the fact that shell scripts can generate and execute shell scripts, thus rendering the question of "strictly conforming" as equivalent to the Stopping Problem.)
(Full disclosure: I was a working member and committee leader within IEEE-CS TCOS, the creators of the POSIX family of standards, from 1988-1999.)
If not, is there any way to verify compliance of myscript.sh?
This is basically a case of Quality Assurance. Start with:
code review
unit tests (yes, I've done this)
functional tests
perform the test suite with as many different shell programs as you can find.
(ash, bash, dash, ksh93, mksh, zsh)
Personally, I aim for the common set of extensions as supported by bash and ksh93. They're the oldest and most widely available interpreters of the shell language available.
EDIT Recently I happened upon rylnd/shpec - a testing framework for your shell code. You can describe features of your code in test cases, and specify how they can be verified.
Disclosure: I helped making it work across bash, ksh, and dash.

Advantages and disadvantages between zsh and emacs' (e)shell

i have currently switched over to emacs (aquamacs) and am in the process of migrating my entire workflow into it one step at a time (org-mode, dired, etc., from pathfinder, notational velocity, etc.).
the one thing i have yet to try (and seems to be the biggest obstacle thus far) is the built-in emacs shell (shell and/or eshell, here on referred to as "eshell"), due to having zsh setup perfectly for me. unsure if there is a way to essentially mirror/minimize the conversion/adaptation steps required.....
my questions:
can eshell be treated as a superset of zsh (i.e., eshell can do everything that zsh can, plus more)? i assume eshell lacks quite a bit compared to standard shells (bash, zsh, ksh, tcsh, etc.), otherwise it would be one of the standard shells (correct me if i'm wrong to think about it that way).
what are the main limitations in using eshell over zsh? any folks switch from zsh to eshell and feel there are aspects of zsh you critically miss?
anyone know of any links/resources doing a zsh/eshell feature comparison?
further, any resources on making the change from one's usual shell to eshell? advice on workflow migration?
if eshell isn't as "powerful" as zsh, then what advantage does eshell have over zsh? any tips and tricks on using eshell within emacs that would illustrate the time spent learning it?
should one just give up on eshell and continue using zsh if it does everything i think i need? or are the few "power workflows" worth it (of which i'm not aware of)?
thnx in advance.
Regarding M-x eshell:
Eshell is not a stand-alone shell; it's implemented in pure elisp, so can't be run outside emacs, which is why it's not one of the standard shells. It doesn't have its own scripting language like bash/zsh/etc. have; it has elisp, and some command interpretation stuff to make calling elisp a little cleaner.
I can't speak to zsh vs eshell, but I've mostly switched from bash to eshell. 95% of the time, eshell does everything I want or need without any problems. I don't use it for ssh. Also, you can't background a process once it's started (but you can start it backgrounded).
It's going to be really hard, because zsh has a full scripting language, whereas eshell is basically an interface to the elisp interpreter. What are you looking for in an interactive shell? Eshell can probably do most of it. Conditional statements and loops on the command line? Sure. Aliases, functions, wildcards, programmable completion? Sure.
The way I migrated was to basically start from scratch. Every time I ran into something that I didn't like or I wished it did, I'd figure out how to get it to do what I want. For example, eshell uses pcomplete.el for programmable completion, so adding completion functions is pretty easy.
Integration with emacs is the big win for me. You can have elisp functions piped to shell commands. For a silly example, try:message "hello world" | cut -f 1 -d ' ' Some commands (notably grep) get put in emacs buffers, so e.g. you can quickly jump to the results.
Depends on how much time you really spend in emacs. If you do everything in emacs, it's useful, because sometimes it's easier to pipe together elisp commands with other commands through eshell. If you don't find yourself copy&pasting between emacs and your shell too frequently, it's probably not going to be a win, and you're going to have to spend time customizing it to the point you're comfortable with it.
As an alternative to eshell, M-x shell runs your normal shell underneath which interprets all the commands (so doesn't have access to elisp functions), while command-line editing (and therefore programmable completion, history, etc.) is done by emacs. I use it for ssh.
One other alternative is M-x term, which is a terminal emulator inside emacs, and usually runs a shell underneath, and the shell does all of its normal things. Then there's absolutely no conversion/adaptation steps required.
Different Syntax
Since eshell allows mixing elisp code in with shell commands, it has some rather unusual syntax, which you'll need to be careful of.
One thing to watch out for is the syntax for command expansion: zsh uses the syntax
file $(which foo)
but in eshell this means basicaly the same thing as
file (which foo)
which means to run the file command on the result of evaluating the elisp expression (which foo), which typically results in an error like this:
Symbol's function definition is void: which
It turns out that the way to write this in eshell is actually
file ${which foo}
Portability
Since eshell is written in platform-neutral Emacs Lisp code, it works in essentially the same way on Windows-native Emacsen as it does on *nix, right out of the box (though of course you'll probably want coreutils and suchlike); getting shell-mode to work with a *nix shell there is presumably at least somewhat trickier.
I think I have seen some wonkiness with completion of absolute paths, though, because of the colon after the drive letter, but that's not exactly a show-stopper...
I think all your 6 questions can be translated to just one question:
All things can be done in zsh that can be done in Emacs?
The answer is YES and there are more. I'd not say shell, eshell or other some Emacs' mode yet I just say Emacs.
shell, eshell just Emacs's mode, if I can find a way or mode at least in which can do anything that zsh can do, so it answers your question. The way is ansi-term mode in Emacs, it can run zsh inside Emacs perfectly, if you can't do your job in shell or eshell you can switch to ansi-term mode in Emacs, so your question has gone.
eshell just elisped shell and those is not good at interactive/scrolling commands such as top, less, etc.

Recommendation - Zsh vs FishShell. Scripting, productivity and poweruser perse [closed]

Closed. This question is opinion-based. It is not currently accepting answers.
Want to improve this question? Update the question so it can be answered with facts and citations by editing this post.
Closed 4 years ago.
Improve this question
I have spent sometime trying to pick one, on net comparisons are for zsh vs bash and fish vs bash. But, I could not find any comparison for zsh vs fish. I program in C and C++, apart from hello-world types, never done any major scripting. But now trying my hands at python and shell-scripts. Which shell keeps more juice in terms of productivity first and then development?
Or in the end, the power and usability of any shell comes to its _rc files. So am I good enough with bash?
Historically there was a flame ware of sorts between the C shells (CSH and TCSH) and Bash. The complaint against the CSH variants are that they're bad for scripting.
In the years I've been a CLI junkie, I've never done any standalone scripts where the scripting language was picked because that's what my shell was.
I've written a variety of scripts that can broadly be divided into two categories:
Those that help my command line productivity
Those that are not directly related to my command line productivity.
Scripts in category 1. are almost always written in my shell scripting language (often as functions as I'm using ZSH and was previously using BASH both of which support functions).
Scripts in category 2. are written in whatever seems like the most efficient (both development time and running time taken into consideration). I often find myself writing small scripts in Perl, C (compiled, obviously), BASH/ZSH/SH or what ever else I want. I've done a little Python scripting (but not much), and even resort to Java on occasion (compiled-ish, again).
So what am I babbling about? Don't base you choice of shell on its standalone scripting capabilities. Choose your shell for it's utility to you as a shell. Script in whatever else you choose. You'll probably be good enough with BASH as your shell (though I like ZSH a bit more, **/* globbing is nice and a few other small things, but most scripts I've written for ZSH are early identical to their BASH counterparts).
I had the same question and found :
page that compare Unix Shells: Bash, Fish, Ksh, Tcsh, Zsh ;
Bash vs Zsh (vs Fish) a reddit thread ;
What are the best Unix shells?
if you can't find any comparison between zsh vs fish, then try them out yourself. That's the only way you can tell which one you prefer, nobody else can tell you that. Also, define the meaning of productivity. For me, its the abundance of modules and the language's internal capabilities. If you have started with Python, go for it. As for shells, you can learn less of it (not saying totally forget about it), with regards to maybe understanding your rc scripts and other system stuffs etc. Beyond that, Python can do what the shell does.
You'll be most productive in an environment you already know. I used bash for years and its fine. It completes almost everything, can be used with git, mercurial ...

Bash or KornShell (ksh)? [closed]

Closed. This question is off-topic. It is not currently accepting answers.
Want to improve this question? Update the question so it's on-topic for Stack Overflow.
Closed 11 years ago.
Improve this question
I am not new to *nix, however lately I have been spending a lot of time at the prompt. My question is what are the advantages of using KornShell (ksh) or Bash Shell? Where are the pitfalls of using one over the other?
Looking to understand from the perspective of a user, rather than purely scripting.
The difference between Kornshell and Bash are minimal. There are certain advantages one has over the other, but the differences are tiny:
BASH is much easier to set a prompt that displays the current directory. To do the same in Kornshell is hackish.
Kornshell has associative arrays and BASH doesn't. Now, the last time I used Associative arrays was... Let me think... Never.
Kornshell handles loop syntax a bit better. You can usually set a value in a Kornshell loop and have it available after the loop.
Bash handles getting exit codes from pipes in a cleaner way.
Kornshell has the print command which is way better than the echo command.
Bash has tab completions. In older versions
Kornshell has the r history command that allows me to quickly rerun older commands.
Kornshell has the syntax cd old new which replaces old with new in your directory and CDs over there. It's convenient when you have are in a directory called /foo/bar/barfoo/one/bar/bar/foo/bar and you need to cd to /foo/bar/barfoo/two/bar/bar/foo/bar In Kornshell, you can simply do cd one two and be done with it. In BASH, you'd have to cd ../../../../../two/bar/bar/foo/bar.
I'm an old Kornshell guy because I learned Unix in the 1990s, and that was the shell of choice back then. I can use Bash, but I get frustrated by it at times because in habit I use some minor feature that Kornshell has that BASH doesn't and it doesn't work. So, whenever possible, I set Kornshell as my default.
However, I am going to tell you to learn BASH. Bash is now implemented on most Unix systems as well as on Linux, and there are simply more resources available for learning BASH and getting help than Kornshell. If you need to do something exotic in BASH, you can go on Stackoverflow, post your question, and you'll get a dozen answers in a few minutes -- and some of them will even be correct!.
If you have a Kornshell question and post it on Stackoverflow, you'll have to wait for some old past their prime hacker like me wake up from his nap before you get an answer. And, forget getting any response if they're serving pudding up in the old age home that day.
BASH is simply the shell of choice now, so if you've got to learn something, might as well go with what is popular.
Bash.
The various UNIX and Linux implementations have various different source level implementations of ksh, some of which are real ksh, some of which are pdksh implementations and some of which are just symlinks to some other shell that has a "ksh" personality. This can lead to weird differences in execution behavior.
At least with bash you can be sure that it's a single code base, and all you need worry about is what (usually minimum) version of bash is installed. Having done a lot of scripting on pretty much every modern (and not-so-modern) UNIX, programming to bash is more reliably consistent in my experience.
I'm a korn-shell veteran, so know that I speak from that perspective.
However, I have been comfortable with Bourne shell, ksh88, and ksh93, and for the most I know which features are supported in which. (I should skip ksh88 here, as it's not widely distributed anymore.)
For interactive use, take whatever fits your need. Experiment. I like being able to use the same shell for interactive use and for programming.
I went from ksh88 on SVR2 to tcsh, to ksh88sun (which added significant internationalisation support) and ksh93. I tried bash, and hated it because
it flattened my history. Then I discovered shopt -s lithist and all was well.
(The lithist option assures that newlines are preserved in your command
history.)
For shell programming, I'd seriously recommend ksh93 if you want a consistent programming language, good POSIX conformance, and good performance, as many common unix commands can be available as builtin functions.
If you want portability use at least both. And make sure you have a good test suite.
There are many subtle differences between shells. Consider for example reading from a pipe:
b=42 && echo one two three four |
read a b junk && echo $b
This will produce different results in different shells. The korn-shell runs pipelines from back to front; the last element in the pipeline runs in the current process. Bash did not support this useful behaviour until v4.x, and even then, it's not the default.
Another example illustrating consistency: The echo command itself, which was made obsolete by the split between BSD and SYSV unix, and each introduced their own convention for not printing newlines (and other behaviour). The result of this can still be seen in many 'configure' scripts.
Ksh took a radical approach to that - and introduced the print command, which actually supports both methods (the -n option from BSD, and the trailing \c special character from SYSV)
However, for serious systems programming I'd recommend something other than a shell, like python, perl. Or take it a step further, and use a platform like puppet - which allows you to watch and correct the state of whole clusters of systems, with good auditing.
Shell programming is like swimming in uncharted waters, or worse.
Programming in any language requires familiarity with its syntax, its interfaces and behaviour. Shell programming isn't any different.
This is a bit of a Unix vs Linux battle. Most if not all Linux distributions have bash installed and ksh optional. Most Unix systems, like Solaris, AIX and HPUX have ksh as default.
Personally I always use ksh, I love the vi completion and I pretty much use Solaris for everything.
For scripts, I always use ksh because it smooths over gotchas.
But I find bash more comfortable for interactive use. For me the emacs key bindings and tab completion are the main benefits. But that's mostly force of habit, not any technical issue with ksh.
I don't have experience with ksh, but I have used both bash and zsh. I prefer zsh over bash because of its support for very powerful file globbing, variable expansion modifiers, and faster tab completion.
Here's a quick intro: http://friedcpu.wordpress.com/2007/07/24/zsh-the-last-shell-youll-ever-need/
For one thing, bash has tab completion. This alone is enough to make me prefer it over ksh.
Z shell has a good combination of ksh's unique features with the nice things that bash provides, plus a lot more stuff on top of that.
#foxxtrot
Actually, the standard shell is Bourne shell (sh). /bin/sh on Linux is actually bash, but if you're aiming for cross-platform scripts, you're better off sticking to features of the original Bourne shell or writing it in something like perl.
My answer would be 'pick one and learn how to use it'. They're both decent shells; bash probably has more bells and whistles, but they both have the basic features you'll want. bash is more universally available these days. If you're using Linux all the time, just stick with it.
If you're programming, trying to stick to plain 'sh' for portability is good practice, but then with bash available so widely these days that bit of advice is probably a bit old-fashioned.
Learn how to use completion and your shell history; read the manpage occasionally and try to learn a few new things.
Available in most UNIX system, ksh is standard-comliant, clearly designed, well-rounded.
I think books,helps in ksh is enough and clear, especially the O'Reilly book.
Bash is a mass. I keep it as root login shell for Linux at home only.
For interactive use, I prefer zsh on Linux/UNIX. I run scripts in zsh, but I'll test most of my scripts, functions in AIX ksh though.
Bash is the benchmark, but that's mostly because you can be reasonably sure it's installed on every *nix out there. If you're planning to distribute the scripts, use Bash.
I can not really address the actual programming differences between the shells, unfortunately.
Bash is the standard for Linux.
My experience is that it is easier to find help for bash than for ksh or csh.

Resources