First, let's go through some typical sources of frustration with Bash.
Bash programmers know that spacing matters:
a = `pwd` # incorrect assignment a=`pwd` # correct assignment
if [-n $some_string] # incorrect- spaces must follow and preceed square brackets then echo $some_string "is not null" fi if [ -n $some_string ] # this one is correct then echo $some_string "is not null" fi
The reason for this is that Bash divides each line into words, delimited by each whitespace. The first word is seen as the name of the command to be executed, while the following words are the arguments to that command.
So, in the variable assignment above, Bash thinks that
a is a command,
which does not exist.
Same goes for the if statements:
[ is a command and, in this case,
-n is an argument. Without the whitespace, Bash will think that
[-n is a command, and will return an error since it is not valid.
One slight note about
[: historically, it was not a shell builtin. Rather,
it was a separate executable that received the expresson as arguments and
returned a result. If you didn't surround the
[ with space, the
shell would be searching $PATH for a different filename (and not find it).
Another common source of error and frustration: wordsplitting. Bash uses parameter expansion, replacing variables with their values, to be able to access the data stored in variables. Without double-quoting, wordsplitting occurs in the expansion (new words will be created at every whitespace).
Take the following example:
var="-n -e -v" echo $var
All thanks to wordsplitting.
var="-n -e -v" echo "$var"
-n -e -v
In a larger example, take this file, named
#!/bin/bash printf "%d args:" $# printf " <%s>" "$@" echo
Consider these commands:
var="This is a variable"; args "$var"
1 args: <This is a variable>
var="This is a variable"; args $var
4 args: <This> <is> <a> <variable>
A discrepancy in Bash that also leads to ambiguity (*frustration)
is new test (
old test (
[). Both actions essentially do the same thing,
except for this major difference: wordsplitting and
glob expansion doesn't happen in new test, because it is a keyword
and not a builtin, like old test. Since new test is a keyword,
it parses its own arguments and does the expansion itself,
taking the result as a single argument even if the result contains whitespaces.
Have you ever tried to edit a global variable inside of a function?
Or inside of any other action that results in the creation of a
subshell? Did it work out?
It didn't work out because subshells inherit variables from their parent shells, but a subshell cannot modify the environment of its parent shell You can only return a numeric value from functions, between 0-255. If you want to return anything else, you would have to echo the information and capture it with command substitution, or write to a temporary file and source the variables. Both seem like subpar solutions.
Having two ways to execute commands,
is not clear and adds ambiguity to programs. These two commands are
Bash performs the expansion by executing command and replacing the com- mand substitution with the standard output of the command, with any trailing newlines deleted. Embedded newlines are not deleted, but they may be removed during word splitting. The command substitution $(cat file) can be replaced by the equivalent but faster $(< file). When the old-style backquote form of substitution is used, backslash retains its literal meaning except when followed by $, `, or \. The first backquote not preceded by a backslash terminates the command sub- stitution. When using the $(command) form, all characters between the parentheses make up the command; none are treated specially.
In a new language, I'd like to see the following:
- More whitespace, for the sake of clarity. But also, I don't think lack of whitespace should result in as much errors as Bash has now.
- Different parameter expansion. There needs to be some means of replacing variable names with their values, but it is too error-prone the way it is now.
- Clear and unique keywords and operations to eliminate ambiguity.
Should the only type be strings (disregarding
declare)? Is this a problem?
Each line represents a command and its arguments? Is this a problem?
Is it a problem that Bash doesn't display errors for undeclared variables?
Function returns- only numeric. Issue?
Inconsistency in control flow structures.
if ends with
while end with
Bash is not self-contained and does not have a standard library. Scripts depend on the environment you are working in, which typically makes scripts have a bunch of moving parts. Also, a Bash script generally uses a lot of other small languages, like Awk, Sed, and Expect. This is kind of just part of the shell game, but better integration is desired.
Is the lack of simple arithmetic operations a problem?
Portability vs features?