UNIX Shells Notes

 

 

13 September 2004

 

Contents

1      Bourne Shell.. 3

1.1       Arrays. 3

1.2       Control Structures. 3

1.2.1        Conditionals. 3

1.2.2        while. 3

1.2.3        for. 3

1.3       Debugging.. 4

1.4       Functions. 4

1.5       Here Doc.. 4

1.6       Input from stdin.. 4

1.6.1        Solaris only. 4

1.7       Operators. 4

1.7.1        Arithmetic Operators. 4

1.7.2        Comparison Operators (Numeric) 5

1.7.3        Comparison Operators (String) 5

1.7.4        Logical Operators. 5

1.8       Output. 5

1.8.1        Without a end of line character. 5

1.9       Positional Parameters (program & function) 5

1.10     Regular Expressions. 5

1.11     Signals. 6

1.12     Variables. 6

1.12.1      Assignment 6

1.12.2      Evaluation. 6

1.12.3      Special Variables. 6

2      C Shell Syntax.. 6

2.1       Control Structures. 7

2.1.1        Conditional 7

2.1.2        Conditional Expressions. 7

2.2       Variables. 8

3      C Shell (Why NOT to use it for programming) 8

3.1       File Descriptors. 8

3.1.1        Writing Files. 9

3.1.2        Reading Files. 9

3.1.3        Closing FDs. 10

3.1.4        More Elaborate Combinations. 10

3.2       Command Orthogonality.. 11

3.2.1        Built-ins. 11

3.2.2        Flow control 11

3.2.3        Stupid parsing bugs. 12

3.3       Signals. 13

3.4       Quoting.. 13

3.5       Variable Syntax.. 14

3.6       Expression Evaluation.. 15

3.7       Error Handling.. 16

3.8       Random Bugs. 17

3.9       Summary.. 17

4      Korn Shell.. 18

4.1       Regular Expressions. 18

4.2       functions. 19

4.3       Control Structures. 19

4.3.1        for. 19

4.3.2        while, until 20

4.3.3        if – then – else. 20

4.4       vi Command Line Editing.. 21

4.4.1        Command completion. 21

5      Misc.. 21

 


1         Bourne Shell

 

1.1      Arrays

 

Not supported in Bourne shell.  Use Korn or C shell.

 

1.2      Control Structures

1.2.1      Conditionals

 

1.2.1.1       case

 

case VARIABLE in

PATTERN1) COMMAND1;;

PATTERN2) COMMAND2;;

*) DEFAULT_COMMAND;;

esac

1.2.1.2       if

 

if CONDITION1; then COMMAND1

elif CONDITION2; then COMMAND2

else; COMMAND3; fi

 

Example:

 

if [ ! -w $LOG ]

then

  echo "Cannot write to $LOG.\nExiting."

  exit 1

fi

 

1.2.1.3       Short-Circuit

 

[ $? -eq 0 -a -n "$server" ] && return 0 || sleep 1

 

1.2.2      while

 

while CONDITION

do

BODY

done

 

cat /tmp/junk | while read pid; do kill $pid; done

 

1.2.3      for

 

wait_nis ()

{

        for i in 1 2 3 4 5; do

                server=`/usr/bin/ypwhich 2>/dev/null`

                [ $? -eq 0 -a -n "$server" ] && return 0 || sleep 1

        done

        return 1

}

 

1.3      Debugging

 

#!/bin/sh –xv

 

1.4      Functions

 

defintion my_func() { }

invocation my_func arg1 arg2 etc

exit leave script

return back to place where function was called

 

1.5      Here Doc

 

cat >$1 <<!

var1=val1

var2=val2

!

 

1.6      Input from stdin

 

read VARIABLE

 

1.6.1      Solaris only

 

/usr/bin/ckyorn

/usr/sadm/bin/erryorn, helpyorn, valyorn

/usr/bin/ckpath

-a absolute path

-d defaultpath the default path is not validated

-f pathname must be regular file

-o pathname must exist (“Old”)

-p prompt

-r pathname must be Readable

-t pathname must be createable (“Touchable”); will be created if doesn’t exist

/usr/sadm/bin/errpath, helppath, valpath

-w pathname must be Writeable

-x pathname must be eXecutable

-y pathname must be a directory

 

1.7      Operators

1.7.1      Arithmetic Operators

 

A=`expr $B + $C`

 

1.7.2      Comparison Operators (Numeric)

 

See “man test”.

 

-eq  equal to

-ge  greater than or equal to

-gt   greater than

-lt    less than

 

 

[ $VAR1 -eq 1 ] (-ne, -gt, -lt etc; see man test)

 

NOTE: If the value of $VAR1 is a string, not a number, it will evaluate to the numeric value 0.

 

1.7.3      Comparison Operators (String)

 

See “man test”.

 

equality [ “$VAR” = “LITERAL” ]

inequality test “$VAR1” != “$VAR2

length non-zero [ -n “STRING” ] (note: surround even $VARIABLE with double quotes, otherwise test interprets $VARIABLE as undefined when $VARIABLE is the empty string)

length zero [ -z “STRING” ]

 

1.7.4      Logical Operators

 

-a logical and

-o logical or

 

1.8      Output

 

1.8.1      Without a end of line character

echo “some text\c”

 

1.9      Positional Parameters (program & function)

 

$0 $1 $2 etc

$#    (number of args)

$*    (all args)

1.10Regular Expressions

 

colon (:) prints to stdout the number of bytes matched;  syntax expr STRING : REGEXP

STRING = variable or literal string

REGEXP is anchored at beginning with implicit ^

example expr "junk yard" : '.*nk' (prints 4)

 

1.11Signals

 

trap -l Lists signal numbers and names

trap -p Prints commands associated with each signal

 

1.12Variables

1.12.1 Assignment

 

There must be no white space between the variable name, the equal sign and the value.  For example:

 

ypserv_running=`$RPCINFO | $GREP ypserv`

not

ypserv_running = `$RPCINFO | $GREP ypserv`

 

1.12.2 Evaluation

 

$A value of A if A defined; otherwise nothing

 

${A-B} value of A if A defined; otherwise B.  A must be a variable.  B can be a variable or a literal string.

Example 1:

cmd="~/.kshrc"

cmd=${1-$cmd}

echo "'$cmd'"

 

Example 2:

cmd=${*-~/.kshrc}

echo "'$cmd'"

 

${A=B} value of A if A defined; otherwise B, A set to B

 

${A?TEXT} value of A if A defined; otherwise print TEXT and exit shell

 

${A+B} B if A defined; otherwise nothing

 

1.12.3 Special Variables

 

$* (all program/function args)

$# (number of program args)

$$ (pid of this shell process)

$? (return code from previous command)

$@ (???)

 

2         C Shell Syntax

 

See docs in C Shell subdirectory.

 

2.1      Control Structures

 

2.1.1      Conditional

 

if (expression) simple command

 

if (expression) then

  ...

else

  ...

endif

 

 

Example:

 

---------------- example.csh ---------------

#!/bin/csh -f

 

set OS = `uname`

if ($OS == "IRIX") then

  set ps_command="ps -edf"

else if ($OS == "SunOS") then

  set ps_command="ps -aux"

else

  echo "Unknown Operating System"

endif

 

echo $ps_command

---------------- example.csh ---------------

 

2.1.2      Conditional Expressions

 

The expressions used in the while and if commands are similar to C language expressions, with these exceptions:

 

=~

If the right hand side matches a pattern, (i.e., similar to filename matching, with asterisks and question marks.) the condition is true.

!~

If the right hand side doesn't match a pattern, the condition is true.

-d $var

True if the file is a directory.

-e $var

True if the file exists.

-f $var

True if the file is a file. (I.e., not a directory)

-o $var

True if the file is owned by the user.

-r $var

True if the user has read access.

-w $var

True if the user has write access.

-x $var

True if the user has execute access.

-z $var

True if the file is zero-length.

 

2.2      Variables

 

There are two types of variables available to the c-shell programmer. The string variable and the numerical variable.

 

The syntax for setting a c-shell variable is "set name=value"

% set inputfile=my_input

 

The syntax for setting a numerical variable is "@ name=value"

@ i=5

 

Variables are then referenced with a dollar sign "$".

 

3         C Shell (Why NOT to use it for programming)

 

http://www.faqs.org/faqs/unix-faq/shell/csh-whynot/

 

The following periodic article answers in excruciating detail
the frequently asked question "Why shouldn't I program in csh?".
It is available for anon FTP from perl.com in /pub/perl/versus/csh.whynot.gz
 
               *** CSH PROGRAMMING CONSIDERED HARMFUL ***
 
    Resolved: The csh is a tool utterly inadequate for programming, 
              and its use for such purposes should be strictly banned!
 
I am continually shocked and dismayed to see people write test cases,
install scripts, and other random hackery using the csh.  Lack of
proficiency in the Bourne shell has been known to cause errors in /etc/rc
and .cronrc files, which is a problem, because you *must* write these files
in that language.
 
The csh is seductive because the conditionals are more C-like, so the path
of least resistance is chosen and a csh script is written.  Sadly, this is
a lost cause, and the programmer seldom even realizes it, even when they
find that many simple things they wish to do range from cumbersome to
impossible in the csh.
 
 

3.1      File Descriptors

 
The most common problem encountered in csh programming is that
you can't do file-descriptor manipulation.  All you are able to 
do is redirect stdin, or stdout, or dup stderr into stdout. 
Bourne-compatible shells offer you an abundance of more exotic
possibilities.    
 

3.1.1      Writing Files

 
In the Bourne shell, you can open or dup arbitrary file descriptors.
For example, 
 
    exec 2>errs.out
 
means that from then on, stderr goes into errs file.
 
Or what if you just want to throw away stderr and leave stdout
alone?    Pretty simple operation, eh?
 
    cmd 2>/dev/null
 
Works in the Bourne shell.  In the csh, you can only make a pitiful 
attempt like this:
 
    (cmd > /dev/tty) >& /dev/null
 
But who said that stdout was my tty?  So it's wrong.  This simple
operation *CANNOT BE DONE* in the csh.
 
 
Along these same lines, you can't direct error messages in csh scripts
out stderr as is considered proper.  In the Bourne shell, you might say:
 
        echo "$0: cannot find $file" 1>&2
 
but in the csh, you can't redirect stdout out stderr, so you end
up doing something silly like this:
 
        sh -c 'echo "$0: cannot find $file" 1>&2'
 

3.1.2      Reading Files

 
In the csh, all you've got is $<, which reads a line from your tty.  What
if you've redirected stdin?  Tough noogies, you still get your tty, which 
you really can't redirect.  Now, the read statement 
in the Bourne shell allows you to read from stdin, which catches
redirection.  It also means that you can do things like this:
 
    exec 3<file1
    exec 4<file2
 
Now you can read from fd 3 and get lines from file1, or from file2 through
fd 4.   In modern, Bourne-like shells, this suffices: 
 
    read some_var 0<&3
    read another_var 0<&4
 
Although in older ones where read only goes from 0, you trick it:
 
    exec 5<&0  # save old stdin
    exec 0<&3; read some_var
    exec 0<&4; read another_var
    exec 0<&5  # restore it
 
 

3.1.3      Closing FDs

 
In the Bourne shell, you can close file descriptors you don't
want open, like 2>&-, which isn't the same as redirecting it
to /dev/null.
 

3.1.4      More Elaborate Combinations

 
Maybe you want to pipe stderr to a command and leave stdout alone.
Not too hard an idea, right?  You can't do this in the csh as I
mentioned in 1a.  In a Bourne shell, you can do things like this:
 
    exec 3>&1; grep yyy xxx 2>&1 1>&3 3>&- | sed s/file/foobar/ 1>&2 3>&-
    grep: xxx: No such foobar or directory
 
Normal output would be unaffected.  The closes there were in case
something really cared about all its FDs.  We send stderr to sed,
and then put it back out 2.
 
Consider the pipeline:
 
    A | B | C
 
You want to know the status of C, well, that's easy: it's in $?, or
$status in csh.  But if you want it from A, you're out of luck -- if
you're in the csh, that is.  In the Bourne shell, you can get it, although
doing so is a bit tricky.  Here's something I had to do where I ran dd's
stderr into a grep -v pipe to get rid of the records in/out noise, but had
to return the dd's exit status, not the grep's:
 
    device=/dev/rmt8
    dd_noise='^[0-9]+\+[0-9]+ records (in|out)$'
    exec 3>&1
    status=`((dd if=$device ibs=64k 2>&1 1>&3 3>&- 4>&-; echo $? >&4) |
               egrep -v "$dd_noise" 1>&2 3>&- 4>&-) 4>&1`
    exit $status;
 
 
The csh has also been known to close all open file descriptors besides
the ones it knows about, making it unsuitable for applications that 
intend to inherit open file descriptors.
 
 

3.2      Command Orthogonality

 

3.2.1      Built-ins

 
The csh is a horrid botch with its built-ins.  You can't put them
together in many reasonable ways.   Even simple little things like this:    
 
            % time | echo
 
which while nonsensical, shouldn't give me this message:
 
            Reset tty pgrp from 9341 to 26678
 
Others are more fun:
 
            % sleep 1 | while
            while: Too few arguments.
            [5] 9402
            % jobs
            [5]     9402 Done                 sleep |
 
 
Some can even hang your shell.  Try typing ^Z while you're sourcing 
something, or redirecting a source command.  Just make sure you have
another window handy.  Or try 
 
    % history | more
 
on some systems.
 
Aliases are not evaluated everywhere you would like them do be:
 
    % alias lu 'ls -u'
    % lu
    HISTORY  News     bin      fortran  lib      lyrics   misc     tex
    Mail     TEX      dehnung  hpview   logs     mbox     netlib
    % repeat 3 lu
    lu: Command not found.
    lu: Command not found.
    lu: Command not found.
 
    % time lu
    lu: Command not found.
 
 

3.2.2      Flow control

 
You can't mix flow-control and commands, like this:
    
    who | while read line; do
        echo "gotta $line"
    done
 
 
You can't combine multiline constructs in a csh using semicolons.
There's no easy way to do this
 
    alias cmd 'if (foo) then bar; else snark; endif'
 
 
You can't perform redirections with if statements that are
evaluated solely for their exit status:
 
    if ( { grep vt100 /etc/termcap > /dev/null } ) echo ok
 
And even pipes don't work:
 
    if ( { grep vt100 /etc/termcap | sed 's/$/###' } ) echo ok
 
But these work just fine in the Bourne shell:
 
    if grep vt100 /etc/termcap > /dev/null ; then echo ok; fi   
 
    if grep vt100 /etc/termcap | sed 's/$/###/' ; then echo ok; fi
 
 
Consider the following reasonable construct:
 
  if ( { command1 | command2 } ) then
      ...
  endif
 
The output of command1 won't go into the input of command2.  You will get
the output of both commands on standard output.  No error is raised.  In
the Bourne shell or its clones, you would say 
 
    if command1 | command2 ; then
        ...
    fi
 
 

3.2.3      Stupid parsing bugs

 
Certain reasonable things just don't work, like this:
 
    % kill -1 `cat foo`
    `cat foo`: Ambiguous.
 
But this is ok:
 
    % /bin/kill -1 `cat foo`
 
If you have a stopped job:
 
    [2]     Stopped              rlogin globhost
 
You should be able to kill it with 
 
    % kill %?glob
    kill: No match
 
but
 
    % fg %?glob
 
works.
 
White space can matter:
 
    if(expr)
 
may fail on some versions of csh, while
 
    if (expr)
 
works!  Your vendor may have attempted to fix this bug, but odds are good
that their csh still won't be able to handle
 
    if(0) then
      if(1) then
          echo A: got here
      else
          echo B: got here
      endif
      echo We should never execute this statement
    endif
 

3.3      Signals

 
In the csh, all you can do with signals is trap SIGINT.  In the Bourne
shell, you can trap any signal, or the end-of-program exit.    For example,
to blow away a tempfile on any of a variety of signals:
 
    $ trap 'rm -f /usr/adm/tmp/i$$ ;
            echo "ERROR: abnormal exit";
            exit' 1 2 3 15
 
    $ trap 'rm tmp.$$' 0   # on program exit
 

3.4      Quoting

 
You can't quote things reasonably in the csh:
 
    set foo = "Bill asked, \"How's tricks?\""
 
doesn't work.  This makes it really hard to construct strings with
mixed quotes in them.  In the Bourne shell, this works just fine. 
In fact, so does this:
 
     cd /mnt; /usr/ucb/finger -m -s `ls \`u\``
 
Dollar signs cannot be escaped in double quotes in the csh.  Ug.
 
    set foo = "this is a \$dollar quoted and this is $HOME not quoted" 
    dollar: Undefined variable.
 
You have to use backslashes for newlines, and it's just darn hard to
get them into strings sometimes.
 
    set foo = "this \
    and that";
    echo $foo
    this  and that
    echo "$foo"
    Unmatched ".  
 
Say what?  You don't have these problems in the Bourne shell, where it's
just fine to write things like this:
 
    echo       'This is 
             some text that contains
             several newlines.'
 
 
As distributed, quoting history references is a challenge.  Consider:
 
    % mail adec23!alberta!pixel.Convex.COM!tchrist
    alberta!pixel.Convex.COM!tchri: Event not found.
 
 

3.5      Variable Syntax

 
There's this big difference between global (environment) and local
(shell) variables.  In csh, you use a totally different syntax 
to set one from the other.  
 
In the Bourne shell, this 
    VAR=foo cmds args
 is the same as
    (export VAR; VAR=foo; cmd args)
or csh's
    (setenv VAR;  cmd args)
 
You can't use :t, :h, etc on envariables.  Watch:
        echo Try testing with $SHELL:t
 
It's really nice to be able to say
    
    ${PAGER-more}
or
    FOO=${BAR:-${BAZ}}
 
to be able to run the user's PAGER if set, and more otherwise.
You can't do this in the csh.  It takes more verbiage.
 
You can't get the process number of the last background command from the
csh, something you might like to do if you're starting up several jobs in
the background.  In the Bourne shell, the pid of the last command put in
the background is available in $!.
 
The csh is also flaky about what it does when it imports an 
environment variable into a local shell variable, as it does
with HOME, USER, PATH, and TERM.  Consider this:
 
    % setenv TERM '`/bin/ls -l / > /dev/tty`'
    % csh -f
 
And watch the fun!
 
 

3.6      Expression Evaluation

 
Consider this statement in the csh:
 
 
    if ($?MANPAGER) setenv PAGER $MANPAGER
 
 
Despite your attempts to only set PAGER when you want
to, the csh aborts:
 
    MANPAGER: Undefined variable.
 
That's because it parses the whole line anyway AND EVALUATES IT!
You have to write this:
 
    if ($?MANPAGER) then
        setenv PAGER $MANPAGER
    endif
 
That's the same problem you have here:
 
    if ($?X && $X == 'foo') echo ok
    X: Undefined variable
 
This forces you to write a couple nested if statements.  This is highly
undesirable because it renders short-circuit booleans useless in
situations like these.  If the csh were the really C-like, you would
expect to be able to safely employ this kind of logic.  Consider the
common C construct:
 
    if (p && p->member) 
 
Undefined variables are not fatal errors in the Bourne shell, so 
this issue does not arise there.
 
While the csh does have built-in expression handling, it's not
what you might think.  In fact, it's space sensitive.  This is an
error
 
   @ a = 4/2
 
but this is ok
 
   @ a = 4 / 2
 
 
The ad hoc parsing csh employs fouls you up in other places 
as well.  Consider:
 
    % alias foo 'echo hi' ; foo
    foo: Command not found.
    % foo
    hi
 

3.7      Error Handling

 
Wouldn't it be nice to know you had an error in your script before
you ran it?   That's what the -n flag is for: just check the syntax.
This is especially good to make sure seldom taken segments of code
code are correct.  Alas, the csh implementation of this doesn't work.
Consider this statement:
 
    exit (i)
 
Of course, they really meant
 
    exit (1)
 
or just
 
    exit 1
 
Either shell will complain about this.  But if you hide this in an if
clause, like so:
 
    #!/bin/csh -fn
    if (1) then
        exit (i)
    endif
 
The csh tells you there's nothing wrong with this script.  The equivalent
construct in the Bourne shell, on the other hand, tells you this:
 
 
    #!/bin/sh -n
    if (1) then
        exit (i)
    endif
 
    /tmp/x: syntax error at line 3: `(' unexpected
 

3.8      Random Bugs

 
Here's one:
 
    fg %?string
    ^Z
    kill  %?string
    No match.
 
Huh? Here's another
 
    !%s%x%s
 
Coredump, or garbage.
 
If you have an alias with backquotes, and use that in backquotes in 
another one, you get a coredump.
 
Try this:
    % repeat 3 echo "/vmu*"
    /vmu*
    /vmunix
    /vmunix
What???
 
 
Here's another one:
 
    % mkdir tst
    % cd tst
    % touch '[foo]bar'
    % foreach var ( * )
    > echo "File named $var"
    > end
    foreach: No match.
 

3.9      Summary

 
While some vendors have fixed some of the csh's bugs (the tcsh also does
much better here), many have added new ones.  Most of its problems can
never be solved because they're not actually bugs per se, but rather the
direct consequences of braindead design decisions.  It's inherently flawed.
 
Do yourself a favor, and if you *have* to write a shell script, do it in the 
Bourne shell.  It's on every UNIX system out there.  However, behavior 
can vary.
 
There are other possibilities.
 
The Korn shell is the preferred programming shell by many sh addicts,
but it still suffers from inherent problems in the Bourne shell's design,
such as parsing and evaluation horrors.  The Korn shell or its
public-domain clones and supersets (like bash) aren't quite so ubiquitous
as sh, so it probably wouldn't be wise to write a sharchive in them that
you post to the net.  When 1003.2 becomes a real standard that companies
are forced to adhere to, then we'll be in much better shape.  Until
then, we'll be stuck with bug-incompatible versions of the sh lying about.
 
The Plan 9 shell, rc, is much cleaner in its parsing and evaluation; it is
not widely available, so you'd be significantly sacrificing portability.
No vendor is shipping it yet.
 
If you don't have to use a shell, but just want an interpreted language,
many other free possibilities present themselves, like Perl, REXX, TCL,
Scheme, or Python.  Of these, Perl is probably the most widely available
on UNIX (and many other) systems and certainly comes with the most
extensive UNIX interface.  Increasing numbers vendors ship Perl with 
their standard systems.  (See the comp.lang.perl FAQ for a list.)
 
If you have a problem that would ordinarily use sed or awk or sh, but it
exceeds their capabilities or must run a little faster, and you don't want
to write the silly thing in C, then Perl may be for you.  You can get
at networking functions, binary data, and most of the C library. There
are also translators to turn your sed and awk scripts into Perl scripts,
as well as a symbolic debugger.  Tchrist's personal rule of thumb is
that if it's the size that fits in a Makefile, it gets written in the
Bourne shell, but anything bigger gets written in Perl.
 
See the comp.lang.{perl,rexx,tcl} newsgroups for details about these
languages (including FAQs), or David Muir Sharnoff's comparison of 
freely available languages and tools in <A HREF="news:comp.lang.misc">comp.lang.misc</A> and <A HREF="news:news.answers">news.answers</A>.
 
NOTE: Doug Hamilton (hamilton@bix.com) has a program that he sells for
profit for little toy non-UNIX systems.  He calls it 'csh' or the 
'hamilton csh', but it's not a csh as it's neither bug nor feature
compatible with the real csh.  Actually, he's fixed a great deal, but
in doing so, has created a totally different shell.
 
-- 
Tom Christiansen      Perl Consultant, Gamer, tchrist@mox.perl.com
"Espousing the eponymous /cgi-bin/perl.exe?FMH.pl execution model is like 
reading a suicide note -- three days too late."
            --Tom Christiansen

 

4         Korn Shell

 

ksh equivalent of csh "source" command is "."

 

4.1      Regular Expressions

 

${A%%pattern} means 'return the value of A after removing from A the

                    longest trailing substring in A that matches

                    PATTERN'

 

${A%pattern} means 'return the value of A after removing from A the

                    shortest trailing substring in A that matches

                    PATTERN'

 

${A##pattern} means 'return the value of A after removing from A the

                    longest leading substring in A that matches

                    PATTERN'

 

${A#pattern} means 'return the value of A after removing from A the

                    shortest leading substring in A that matches

                    PATTERN'

 

!       no match (placed after left curly brace?)

?       matches a single character

*       zero or more characters

[abc]   matches a single character in the set {a, b, c}

[0-5]   matches a single character in the (inclusive) range [0, 5]

 

4.2      functions

 

You can define a function for use with other shell commands. To do this, specify the name of the function followed by a set of parenthesis. The commands that are associated with the name should follow, and be enclosed within braces and separated by semi-colons. The syntax for this is:

name () {list;}

where name is the name of the function and list is a set of commands that are executed when the function is invoked.

 

4.3      Control Structures

 

4.3.1      for

 

for var in word1 word2 .... wordn #Bourne compatible for
do
......
done

Loop over script arguments is done with the following for forms:

for var in $*
for var in "$@"
for var
 

One line for abbreviated form is:

for var in ....; do .....; done

 

4.3.2      while, until

 

Other Korn shell loop commands are while and until that operates the reverse test. The while and until syntax is explained below.

while ((cond))                  until [[ cond ]]
do                              do
   .....                           ......
done                            done

The one line while and until forms for the loop forever condition are:

while true; do ....; done
until false; do ....; done

 

4.3.3      if – then – else

 

In the if command the conditional clause is expressed in the double bracket form and execution is triggered by the true (=0) or false (=1) result of the condition.
Do not forget
<space> separators with square brackets operators.

if [[ .... ]]
then
.....
fi
One line if is achieved with one of the forms:

if [[ cond ]] ; then ......; fi
((cond)) && { ....; ....; } 
[[ cond ]] && { ....; ....; }

The two forms differ for the usage of the <space> characters to delimit test fields. An example of test on numargs with the two syntax forms is:

(($# < 1)) && { print "Usage: $0 args"; exit 1; }
[[ $# < 1 ]] && { print "Usage: $0 args"; exit 1; }

The full if form is:

if ((...))
then
.....
elif ((...))
then
.....
else
.....
fi

 

4.4      vi Command Line Editing

 

4.4.1      Command completion

 

There are three methods, both leaving you in edit mode.  In command mode press:

 

·         * - this expands to a space-separated list of all matching file names
·         \ - this expands to the largest portion of a filename that matches
·         Shift-8

 

5         Misc

 

$? = return code of previous command

 

 

Re: shell script amateur in need of reference

materials online...

 

 

 

From           jrmartin@rainey.blueneptune.com (James R. Martin)

Organization   Blue Neptune Network Services, Inc.

Date           21 Jan 1998 01:44:10 GMT

Newsgroups     comp.unix.shell

Message-ID     <6a3jta$jc$1@sjs-news-01.blueneptune.com>

References     1

 

 

 

Chris (Kerseys@ix.netcom.com) wrote:

: Hi all,

: I'm trying to find some information on scripting in the UNIX ksh.  I

: have *no experience scripting, and was hoping someone could point me

: to some online documentation/examples. 

: I appreciate your time,

: Chris Kersey

: scriptless@kerseyglass.com

 

# shell tutorials, man pages, and documents, non-interactive.

http://www.sct.gu.edu.au/~anthony/info/shell/ # example shells scripts, hints and tips!

http://www.qnis.net/~phil/faq.html

http://biosci.cbs.umn.edu/compfacil/man/ksh.1.html

http://riceinfo.rice.edu/Computer/Documents/Classes/Unix/unix_classes.html

http://www.ecl.udel.edu/~totten/shell/ #shell programming document

http://cdfinfo.in2p3.fr/Services/Informatique/munix.html #ksh complete!

http://landru.unx.com/~pend/dtksh.html #dtksh (incl'd with CDE compliant machs)

http://www.softlab.ntua.gr/unix/docs/sh.txt # SR Bourne's original AT&T doc

http://www.hotdeal.com/softpro/feature/UNIX/Using_UNIX/KornShell_Programmin.html

http://landru.unx.com/DD/advisor/docs/dec95/dec95.pend.shtml # ksh93 with .so

http://www.partner.digital.com/www-swdev/pages/Home/TECH/CDE/htmldocs/Dtksh/dtksh_2.html #dtksh tutorial!

http://www.cs.mun.ca//orientation/node1.html #scripting, etc tutorial!

http://www.cs.princeton.edu/~jlk/ksh93.html #describes KSH93

http://www.readmedotdoc.com/subcat/unix1.html

http://catwoman.tamu.edu/Korn_shell.html

http://www.kzoo.edu/~compserv/infosheets/unix/

http://www.cen.com/mw3/#the-faqs

http://www.intac.com/ .../ksh.1 #ksh man page

http://www.eee.hku.hk/man/solaris/List.1.html

http://www.sci.muni.cz/docs/Unix/ksh.html #k/sh docs!

http://www.cs.princeton.edu/~jlk/research.html #tksh

http://garfield.ir.ucf.edu/manual/aix/bourne.html #bourne tutorial

http://www.ocean.odu.edu/ug/shell_help.html

http://www.learntree.com/ # learning UNIX online

http://cdfinfo.in2p3.fr/Services/Informatique/munix.html # ksh tutorial+utils

 

# shell tutorials, interactive:

http://www.cit.ac.nz/smac/csware.htm #on-line shell tutorial!, $25 fee

http://www.cs.stir.ac.uk/guides/unix/unix.html

 

Many of these URLs are out of date, but as I am sure that the best ones of

them will not only continue to exist but also be the ones of most interest

to you, I submit them for your edification.

 

I add one more, though, not appearing above: start here:

http://www-h.eng.cam.ac.uk/help/tpl/unix/scripts/scripts.html

 

-James

 

 

 

 

 

 

 

 

 

 

# This part parses and validates the input

 

if [  ! "$1" ]

then

   echo

   echo "Usage : $0 dbname tabname"

   echo

   exit 2

fi

 

if [  ! "$2" ]

then

   echo

   echo "Usage : $0 dbname tabname"

   echo

   exit 2

fi

 

db=$1

tabname=$2

export db tabname

 

# uses a for loop on the result of the dbaccess statements. 

# The dbaccess gets a list of column names for processing.

 

for columns in `dbaccess $db  <<-! 2> /dev/null

    output to pipe "cat" without headings

    select colname

      from systables,syscolumns

      where systables.tabid = syscolumns.tabid

      and tabname = "$tabname";

!`

do

 

# Note the second here doc

 

cat <<!

   f_$columns = p_$tabname.$columns ;

!

done

 

 

# The out is formatted say for orders record

#    f_orders_key = p_orders.orders_key ;

#    f_customer_key = p_orders.customer_key ;

#    f_orders_date = p_orders.orders_date ;

 

# This is useful for generating blocks of code without error.

# Well thats how code generators work.