next up previous contents
Next: Korn shell exec, read Up: Korn shell Previous: Korn shell options

Korn shell scripts

Script arguments are the same as in Bourne shell:


$0 command name
$1...$n arguments 1 to n
$# no. of arguments
$? exit status



Arguments can be shifted as in Bourne shell. Script execution can terminate at any place and return an optional exit value:

exit [n]

Checks are enabled either by test or [...] (same as test) or by [[...]]. The expression is separated from brackets by leading and trailing blanks. The double brackets form is a Korn shell enhancement.

[ "$X" = abc ]  && echo string is "abc"         # tcsh
test "$X" = abc && echo string is "abc"         # tcsh
[[ $X = abc ]]  && echo korn                    # korn


Korn Shell String Operators
-n str true if len(str) != 0
-o opt true if opt set
-z str true if len(str) = 0
str1=str2 true if equal strings
str1!=str2 true if .not.equal strings
str1=pattern true if pattern match
str1!=pattern true if pattern .not.match
str1<str2 true if str1 less than str2
str1>str2 true if str1 greater than str2



Example:

> cat kstr
#!/bin/ksh
#-----------kstr: string test with Korn shell
#
echo Proc $0:  strings in Korn shell
echo
# set -x            #uncomment to debug script
X=nice_dog
Y=bad_cat
[[ $X = *dog* ]] && print $X is a nice doggie
[[ $Y = ??????? ]] && print $Y is 7 chars long
X=123
[[ $X = +([0-9]) ]] && print $X is digit
[[ $Y = +([0-9)] ]] || print $Y is alpha
#
#----------end script------------------
> kstr
Proc kstr: strings in Korn shell

nice_dog is a nice doggie
bad_cat is 7 chars long
123 is digit
bad_cat is alpha
>-----------------------
File testing is performed by the following operators prefixed to the file name:
> ksh -c "[[ -a kvar ]] && echo exists"
exists
$ ksh -c "[[ -a kls.ksh ]] || echo no such file"
no such file
$ [[ -a kls.ksh ]] || print no such file
no such file
The ksh -c syntax in the above example is used when executing Ksh commands from another shell and is omitted when the test is performed with Ksh shell.
Ksh test operators are mostly the same as Bourne shell ones, as described in the related table that follows.


Korn Shell Test Operators
-a exists
-b block special file
-c character special file
-d is directory
-e exists
-f is regular
-g setgid bit set
-G matches group ID of current process
-k sticky bit set
-L symbolic link
-n nonzero length string
-o true if named option is on
-O same UID as process
-p FIFO special file
-r readable
-s size > 0
-S socket
-t open and associate to terminal file descriptor
-u user-id bit is set
-w writable
-x executable
-z zero length string
-ef file1 is another name for file2
-nt file1 newer than file2
-ot file1 older than file2



Test can be done also on open files using file descriptor:

$ [[ -r /dev/fd/0 ]] && print read
read
$ exit
Korn shell supports also Fortran like test operators for integer variables:
-eq -ne -le -lt -ge -gt

Ksh control structures are:

case value in # Bourne compatible case
pat1: ...
... ;;

::::

patn: ...
... ;;
esac

Match patterns can be used in case structures. Supported patterns are:


@([a-z]) 		 a lowercase character

@([1-9])*([0-9]) any number starting with 1
Multiple patterns are specified as (pat1 | pat2 | pat3), match criteria are:


? 		    zero or one occurence

* zero or more occurences
@ exactly one occurence
+ one or more occurences
! all strings except pattern
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
Examples of for and if:

> cat kgrep
#!/bin/ksh
#-----------kgrep: search string in all files with header
#-----------usage: kgrep "search string" files
#
echo
PWD=`pwd`
SRC=$1       #set SRC="search string"
shift        #shift 1 argument
for FILE     #loop over files pointed by the for variable FILE
do
    FOUND=`grep "$SRC" $FILE`
    if [[ $? = 0 ]]
    then
      print "*********************"
      print $PWD"/"$FILE
      print ""
      print $FOUND
      print ""
    fi
done
#----------end script------------------
> kgrep  include *.f
*********************
/user/james/fdev/init.f

include 'COM.INC'
include 'DAT.INC'

*********************
/user/james/fdev/array.f

include 'COM.INC'
> grep -l ksh d* ka*
init.f
array.f
Compare kgrep output with grep -l output that is more brief and easy to read, but prints only routine names missing multiple lines matching the search substring.

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

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
Loop conditions are exited with break n where \framebox{\sf n} is the loop nesting level:

for i in a b c
do
  for j in x y
  do
    ((i == b && j == y))
    then
      break 2
    else
      .....
    fi
  done
done
label: .....
#---------------end script-------------

In the above example break 2 transfers control to label:. To interrupt only the inner loop use break. If only a warning condition is detected, use continue instead of break. When implementing loops insert a read statement in critical points to enable loop interruption and script check in case of errors generating endless loops. An example of break and continue is given below.

#!/bin/ksh
#-----------kcond: job control commands with Korn shell
echo Proc $0: if/while/... in Korn shell
echo
(($# >= 1)) && { print "Logged users:\n`who`"; exit 0; }
#
nus=$(who | wc -l)
if ((nus == 1))
then
  print "1 user logged"
elif ((nus == 2))
then
  print "2 users logged"
else
  print ">2 users logged"
fi
#----------------B R E A K-------------------
echo ""
#
set +x            #set trace off
#
set -A rgb R G B Y M C
echo "while example on rgb array ${rgb[*]} - <ret> for next item - break at Y"
((i=0))
while true
  do
    read RET
    if ((i == 3))
    then
      print "break point reached: i should be = 3 and rgb = Y"
      print "break values are:    rgb[$i] --> ${rgb[i]}"; break
    else
      print {$i}-eth RGB item is ${rgb[i]}; ((i=i+1));
    fi
done
#----------------C O N T I N U E-------------------
echo "--------------------------"
echo "while example on rgb array ${rgb[*]} - <ret> for next  - continue at Y"
((i=0))
while ((i <= 5))
  do
    read RET
    if ((i == 3))
    then
      print "continue point reached: i should be = 3 and rgb = Y !!!!!"
      print "continue loop for remaining colors\n";
      print {$i}-ETH rgb ITEM IS ${rgb[i]}; ((i=i+1)); continue
    else
      print {$i}-ETH rgb ITEM IS ${rgb[i]}; ((i=i+1));
    fi
done
#---------------------------------------------------------

Command set +x can be changed in set -x to debug script. Note the \framebox{\tt read RET} statements that protects script from infinite loops. A <ret> is enough to procede, <ctrl>c interrupts the script. The script produces the following output.

> kcond
Proc kcond: if/while/... in Korn shell

1 user logged

while example on rgb array R G B Y M C - <ret> for next item - break at Y
{0}-eth RGB item is R
{1}-eth RGB item is G
{2}-eth RGB item is B
break point reached: i should be = 3 and rgb = Y
break values are:    rgb[3] --> Y
-----------------------------------
while example on rgb array R G B Y M C - <ret> for next  - continue at Y
{0}-ETH rgb ITEM IS R
>
A very simple way to generate \framebox{\bf menus} using Ksh is given by the \framebox{\sf select} command.

select menu_var in CHOICE1 ..... CHOICEn
do
  ......
done
The select command displays the enumerated menu item list followed by the #? prompt waiting for item value. Prompt value can be set:

$ typeset -x PS3="my pmpt>"

The user types the no. corresponding to the menu item. The typed number is stored in the builtin variable REPLY, while the select menu item is stored in the user variable of the select command.
Example:

#--------------------------------------------------------------
> cat kmenu
echo "Proc $0: select (menu) in Korn shell"
echo
typeset -x PS3="Command: "
select i in PAGE PWD DIRSIN DIR END
do
  if [[ $i = END ]]
  then
    print "Exit option"; exit 0
  fi
  print "Selection item $REPLY: $i"
  case $i in
    PAGE*) page $0;;
    PWD*)  pwd;;
    DIRSIN*) dirsin;;
    DIR*) dir;;
  esac
done
#----------------------------------------------------------------
> kmenu
Proc kmenu: select (menu) in Korn shell

1) PAGE
2) PWD
3) DIRSIN
4) DIR
5) END
Command: 3
Selection item 3: DIRSIN
Mar 10
-rwxr-xr-x   1 mary     users        380 Mar 10 12:03 kgrep
Total of 1 files, 0 blocks
Command: 5
Exit option
>
The menu choice list can be given as script arguments with:

select menu_var; do ....; done                  or
select menu_var in "$@"; do ....; done


Korn Shell Print Escape Characters
\a bell
\b backspace
\c do not write newline (use for prompts)
\f formfeed
\n linefeed
\r return
\t tab
\v vertical tab
\\ backslash
\0x up to 3 digits octal no.
Print Options
- treat eveything following - as an argument
-n do not add newline
-p redirect arguments to co-process
-r ignore escape conventions
-R ignore escape; do not interpret -args as options (except -n)
-s redirect arguments to history
-un redirect arguments to file descriptor n
  (default 1, if >3 must be first opened with exec)



next up previous contents
Next: Korn shell exec, read Up: Korn shell Previous: Korn shell options
Marisa Luvisetto
2001-02-05