Thursday, November 17, 2005

Control Flow: Loops

Millions recognize the Shaker hymn, "Simple Gifts" from Aaron Copeland's "Appalachian Spring."

The words begin


'Tis the gift to be simple,
'tis the gift to be free,
'tis the gift to come down where you ought to be,
And when we find ourselves in the place just right,
It will be in the valley of love and delight.


Open Source programmers around the world today, like modern-day Shakers , practice freedom and simplicity. (The Shakers also practiced celibacy, however theirs was voluntary.)

In honor of the Shakers, you should try out the Linux, command-line version of their hymn, which is even simpler:


yes "'Tis the gift to be simple"


Unfortunately, no one can sing that fast.

The shell lets us bring this down to a reasonable pace with a loop:


while true
do
echo "'Tis the gift to be simple"
sleep 3
done


As usual, you should try this out, both in a file and on the command line. Try also substituting the lyrics to the K&R hymn, "Hello, world".

Once you know loops are available, it's surprising how useful they can be. This next loop tells us when the file "MY_LONG_AWAITED_OUTPUT" appears.

while true
do
if test -e MY_LONG_AWAITED_OUPUT
then
printf 'DONE!!!\a\n'
break
fi
done


See if you can use a loop sometime today.

Control Flow: Conditionals

Real programming languages also have control flow constructs, like conditionals and loops. Here's a conditional
#!/bin/bash

# Some variables are built in, and predefined.
# $0 is C's argv[0], or Perl's $0

# $1, $2, etc., are the rest of argv[]/$ARGV
# $* is the whole arg list

# You can even use "test" to test the value of variables

if test "$*" = ""
then
HELLO="hello, world"
else
HELLO="hello $*"
fi

echo $HELLO

As usual, snarf-n-barf this into a file -- call it hello -- make it executable, and run it. Try it both as hello and as hello $LOGNAME .

Try typing this program interactively to see how the interactive shell handles control-flow statements. Watch the prompt change. What's $* for your interactive shell? (Hint: echo $*).

But would anyone use an if ... then ... else ... or even an if ... then ... on the command line? Daily. I'll show practical examples, and some other useful forms for conditionals, too.

(The Boehm-Jacopini theorem says a programming language needs nothing but a "while" and an "if," but language designers know enough not to leave well enough alone. I could write this blog in Basic English, but why would I want to?)

Next up, loops.

Wednesday, November 16, 2005

Variables

If it's a programming language, it needs variables. Here's how you assign a value to a shell variable, and how you get that value back (dereference it).

#!/bin/bash

# Here's how
# you give variables values.

HELLO="hello, world"

# (No spaces allowed around the '=' sign:
# a design botch in the shell.)

# And here's how you use them. Note the dollar sign.

echo $HELLO

Convince yourself that this works interactively, too. Try putting spaces around the equals sign, to see what the error message says. That way, when you make this mistake, you'll recognize it.

I don't know anyone who's crazy about this design (no spaces, '$' to dereference, no '$' to set), but we can no more fix it now than we can fix English syntax. There may be shell scripts still running that were written before you were born. Hindsight's always 20-20.

Unsurprisingly, you can also assign variables the values of other variables. This is a programming language.

GOODBYE=$HELLO
echo $GOODBYE
echo $HELLO

You can also unset a variable.
    
unset HELLO
echo $GOODBYE
echo $HELLO

Tuesday, November 15, 2005

Shebang!

The quickest way to make progress in bash is to bounce back and forth between using it interactivly and non-interactively.

Before we do that, though, it's worth our taking a quick tour of some things you'll see in shell scripts (which is what shell programs are called).

To cut down on confusion, most scripts we show on the tour will do the same thing as yesterday's: print "hello, world." (It was that or "Just Another Perl Hacker" :-)

Here's the second version of yesterday's script.

#!/bin/bash

# "#!" is prononced "shebang" (shell bang)
#
# When a program starts like this,
# the Unix kernel treats it specially,
# and feeds it to a particular interpreter -- in this case, /bin/bash.
#
# When the kernel sends it to bash, bash treats that line as a comment,
# because it starts with a '#'

echo hello, world

# If you don't have bash, use ksh. If you don't have either, us /bin/sh

Cut-and-paste this code into a file, make it executable, and run it. ("Cut-and-paste" is also colloquially known as "snarf-n-barf.")

Try modifying the shebang line to have the kernel send it to other interpreters, like /bin/ksh, /bin/sh, /bin/tcsh, or even /bin/true. What happens?

Claims that "shebang" was originally spelled "Sí bheang" are ill-founded, urban blarney.

Monday, November 14, 2005

The Canonical Program

Perhaps the single most influential book on programming is The C Programming Language, by Brian Kernighan and Dennis Ritchie.

It begins like this:
1.1 Getting Started

The only way to learn a new programming language is by writing programs in it.The first program to write is the same for all languages: Print the words hello, world

This is the basic hurdle; to leap over it you have to be able to create the program text somewhere, compile it successfully, load it, run it, and find out where your output went. With these, mechanical details mastered, everything else is comparatively easy.


Since K&R, everyone's begun this way. No sense going against the crowd if you don't have to. Let's begin.

# The canonical program

echo hello, world # note that '#' starts a comment

You can type these lines into a file, make the file executable, and run it as a command. You can also just type the lines at the command prompt. The result is the same. It's a programming language. It's a command-line language. It's new Shimmer.

(You can omit the comments, but it's more fun to type them in.)

Give it a try.

Sunday, November 13, 2005

What's This Blog About, Anyway?

This blog is about using the shell.

The shell is a full-featured command interpreter that's both a command-line and programming language. By "command-line," I mean you can type, interactively, at a prompt and get things done. By "programming language," I mean you can write programs in the same language.

Having something that does both well is a pleasant surprise.

I'll keep blog posts bite-sized, and I'll make the entries for a week relate to one another.

Topics will progress, but I'll try not to make them too interdependent. I'd like you to be able to jump in and out whenever you want, flitting from topic to topic like a butterfly going from flower to flower, sampling whatever attracts your fancy.

Because shells are just programs, there are a lot of shells for Unix, Linux, and other, similar operating systems. In this blog, when I say "shell," I mean a POSIX-conforming shell, which follows the specs laid out in ISO 9945-2.

In other words, not csh or tcsh, not zsh, not the Massey shell, and not even very old versions of /bin/sh. This still leaves a lot of possibilities.

Also, most commands you'll use in the shell are standalone applications. (Unlike other operating systems, most shell commands aren't built in to the command interpreter.) This means shell programs can depend on the underlying operating system.

You need to see real examples, so I'll focus on programming in bash ("the Bourne-again shell") running on Linux.

Ready?