Indenting bourne shell here documents

The Bourne shell provides here documents to allow block of data to be passed to a process through STDIN. The typical format for a here document is something similar to this:

command <<ARBITRARY_TAG
data to pass 1
data to pass 2
ARBITRARY_TAG

This will send the data between the ARBITRARY_TAG statements to the standard input of the process. In order for this to work, you need to make sure that the data is not indented. If you indent it for readability, you will get a syntax error similar to the following:

./test: line 12: syntax error: unexpected end of file

To allow your here documents to be indented, you can append a “-” to the end of the redirection strings like so:

if [ "${STRING}" = "SOMETHING" ]
then
        somecommand <<-EOF
        this is a string1
        this is a string2
        this is a string3
        EOF
fi



You will need to use tabs to indent the data, but that is a small price to pay for added readability. Nice!

Exiting from a shell script when a failure occurs

While debugging an issue with one of my scripts, I wanted to abort execution and exit when a non-zero return code occurred. I recalled reading about a bash flag that provided this behaviour, and after a few minutes of reading through bash(1) I came across the following set option:

“-e Exit immediately if a simple command (see SHELL GRAMMAR above) exits with a non-zero status. The shell does not exit if the command that fails is part of the command list immediately following a while or until keyword, part of the test in an if statement, part of a && or|| list, or if the command’s return value is being inverted via !. A trap on ERR, if set, is executed before the shell exits.”

So given the following test script that calls a non-existent command /bin/bork:

$ cat test
/bin/bork
echo “Made it after the bork”

We can see that a normal run completes to the end:

$ sh test
test: line 1: /bin/bork: No such file or directory
Made it after the bork

But an invocation with the “-e” option exits when a non-zero return value occurs:

$ sh -e test
test: line 1: /bin/bork: No such file or directory

The bash manual page is full of super interesting stuff, and I just printed it out to learn more! Nice!

Getting sed to substitute a newline on Linux and Solaris hosts

While crafting an install script a week or two ago, I came across an annoying issue with the Solaris sed utility. When I tried to substitute the string ‘, ‘ with a newline, I got this:

$ grep foo gemlist | sed -e ‘s/foo.*(//’ -e ‘s/)//’ -e ‘s/, /\n/g’
2.4n2.3n2.2n2.1

But when I ran the same sustitution with GNU sed, everything worked as expected:

$ grep foo gemlist | gsed -e ‘s/foo.*(//’ -e ‘s/)//’ -e ‘s/, /\n/g’
2.4
2.3
2.2
2.1

It turns out that the Solaris sed is extremely dated, and requires an explicit newline instead of a ‘\n’:

$ grep foo gemlist | gsed -e ‘s/foo.*(//’ -e ‘s/)//’ -e ‘s/, /\
$>/g’
2.4
2.3
2.2
2.1

In the end I found it easier to write my installer in Python, which made life much much easier.

Bash tips

I read through the bash tips on the hacktux website, which brought to light the fact that you can do basic integer math in your bash scripts. This is easily accomplished by using dual parenthesis similar to this:

four=$(( 2 + 2 ))
echo $four

This is good stuff, and I need to replace some old `bc …` and `expr ..` statements with this.