Ksh built-in functions

Calling the many UNIX programs in /bin and elsewhere can be very useful. The one drawback is speed. Every time you call a separate program, there is a lot of overhead in starting it up. So the conciencious programmer always tries to use built-in functions over external ones. In particular, ksh programmers should always try use '[[ ]]' over '[ ]', except where [] is neccessary

The more useful functions in ksh I find are:

An overview for each of the above is given below

typeset

The man page for it gives full details on typeset; however, I find it useful simply to provide function-local variables.
val=1
func(){
	typeset val=2
	echo val in func is $val
}
func
echo after func, top level val is still $val

Read and Set

 read varname
will set the variable varname to have the value of the next line read in from standard input.

What often comes next, is

 set $varname
This sets the argument variables $1, $2, etc to be set as if the program were called with $varname as the argument string to the shellscript. So, if the value of varname is "first second third", then $1="first", $2="second", and $3="third".

Note that if you want to access "double-digit" arguments, you cannot use "$10". it will get interpreted as "$1,""0". To access argument #10 and higher you must explicitly define the limits of the variable string, with braces:

echo ${10}
This is also good to know, if you wish to follow a variable immediately followed by a string. Compare the output from the following lines:
a="A "
echo $astring
echo ${a}string

The test function

In brief, 'test' can let you check the status of files OR string values.
Here are the most common uses for it.
if [[ $? -ne 0 ]] ; then echo status is bad ; fi
if [[ "$var" != "good" ]] ; then echo var is not good ; fi
if [[ ! -f /file/name ]] ; then echo /file/name is not there ; fi
if [[ ! -d /dir/name ]] ; then echo /dir/name is not a directory ; fi

wildcards in test

Please note that [[]] is a special built-in version of test, that is almost, but not 100%, like the standard [].

One large difference is that filename wildcard expansion will be done with the standard test. In contrast, filename wildcard expansion does not work within [[]]. It does string wildcarding instead, and only on the right side. Additionally, it must not be quoted in any way (unlike case statements)

Examples:

if [[ a* == "astring" ]] ; then echo this does not work ; fi
if [[ "astring" == "a*" ]] ; then echo this does not work ; fi
if [[ "astring" == 'a*' ]] ; then echo this does not work ; fi
if [[ "astring" == a* ]] ; then echo this works ; fi
if [[ "astring" = a* ]] ; then echo this works ; fi

Built-in math

The math evaluator is very useful. Everything inside the double-parens gets evaluated with basic math functions. For example;

four=$((2 + 2))
eight=$(($four + 4))
print $(($four * $eight))
# Inside (()), the $ is optional, so the following works...
# but you might want to keep them for assorted reasons..
print $((four * eight))

# even hex to decimal conversions
print $((0xff))

This next example isnt exactly a math routine, but it is a very handy and fast builtin method to go the other way, from decimal to hex (since 'printf' is a ksh builtin function):

printf "%x\n" 255    #this prints out "ff"
printf "%.4x\n" 255  #or if you need a fixed field width number use this
Warning #1: Some versions of ksh allow you to use floating point with $(()). Most do NOT. Warning #2: ksh is very strict about what goes inside the (( )). Every variable you use must have a value, and it must be a numeric value. Otherwise, ksh will most likely treat that line in your script as a failed function call.

Limitations of built-in functions

Be wary of assumptions. Being "built in" is not always faster than an external progam, if an operation is complex. For example, it is trivial to write a shell-only equivalent of the trivial awk usage, "awk '{print $2}'", to print the second column. However, compare them on a long file:


# function to emulate awk '{print $2}'
sh_awk(){
	while read one two three ; do
	print $two
	done
}

# and now, compare the speed of the two methods

time sh_awk </usr/dict/words >/dev/null
time awk '{print $2}' </usr/dict/words >/dev/null

The awk version will be much much faster. This is because ksh scripts are interpreted, each and every time it executes a line. AWK, however, loads up its programming in one go, and figures out what it is doing ONE TIME. Once that overhead has been put aside, it then can repeat its instructions very fast.


TOP of tutorial
Next: Redirection and pipes: Joining things together Prev: Functions
This material is copyrighted by Philip Brown