Nethence Newdoc Olddoc Lab Your IP BBDock  


Warning: those guides are mostly obsolete, please have a look at the new documentation.

UnixWindowsOracleObsoleteHardwareDIYMechanicsScriptsConfigs

KSH development
 
http://pbraun.nethence.com/doc/shells/ksh.html
http://pbraun.nethence.com/doc/lang/kshdev.html
 
Playing with KSH variable names
Simply a variable inside a variable,
# foo=bar
# myvar=foo
# eval "echo \$$myvar"
bar
# eval ok=\$$myvar
# echo $ok
bar
alternative,
# foo=bar
# typeset -n myvar=foo
# echo $myvar
bar
 
Now a variable inside a renamed variable,
# myvar=oo
# eval "echo \$f$myvar"
bar
# eval ok=\$f$myvar
# echo $ok
bar
 
Best practices (KSH88 compilant)
- always use "set -e" at the start of a script, so it exits immediately if a command fails (same as -o xtrace). The drawback for this practice is that it will exit even when it fails to define a variable. For example if this variable returns empty,
emptyvar=`grep ^something /some/file`
it will exit... A workaround is to include the test directly inside a condition to avoid exiting,
[[ -z `grep ^something /some/file` ]] && ...
- always indented code even for small pieces. So you can always rearrange the parts when the it grows
- KSH's "[[" style permits to ommit quotes on string conditions (quite comfortable !)
- use print instead of echo, it's lighter and compilant with all KSH versions. Note about tailing newline omission. Instead of "echo -n" there's,
print "text...\c"
- check for depedencies at program's startup,
[[ -x `whence sed` ]] || die "sed command not found"
note. "whence" is built in KSH, <<hence>> faster than 'which' !
note. stdout isn't printed to the terminal, but into the statement itself
note. if using 'which' against a non existant command, stderr may be printed to the terminal so,
#[[ -x `which sed 2>/dev/null` ]] || die "sed command not found"
- define if not already defined,
USER=${USER:-`logname`}
HOSTNAME=${HOSTNAME:-`hostname`}
- no need to unset subshell variables e.g. for 'read line'
- use "=" for string conditions (although KSH93 understands "==" for that too)
 
Arthmetical conditions and statements
- don't prefix variables with "$" in arthmetical conditions and statements
- use "=" to define a variable inside the arithmetic statement,
(( x = x + y ))
- use "==" for arithmetical conditions,
(( x == y )) && ...
- Increment a counter,
(( x += 1 ))
note. "-=" works too !
note. "(( x++ ))" works with KSH93 only.
 
 
Usage function
Strip the path from $0,
fusage() {
  cat <<EOF9
 
  usage: ${0##*/} ...
 
EOF9
}
 
 
Tips
Print a variable's variable,
var1=ok
var2=var1
eval echo \$$var2
 
 
Getopts
Use getopts to parse command line arguments,
while getopts ab: opts; do
  case $opts in \
  a) print "-a ok";;
  b) print "-b $OPTARG";;
  esac
done
Note. no need to 'shift'
Note. the backslash after 'case ... in' is KSH88 compilant
Note. quoting the manual,
OPTARG  The value of the last option argument processed by the getopts special command.
OPTIND  The index of the last option argument processed by the getopts special command.
Refs :
- "man getopts"
- "man getopt" on HP/UX : set -- `getopt abo: $*`
 
 
Fancy titles
Automated underline,
ftitle() {
titlef=$1
 
print "$titlef"
tmp=`echo $titlef | wc -c`
i=1
until (( $i == $tmp )); do
print '=\c'
(( i += 1 ))
done
print ''
 
unset tmp i titlef
}
 
 
Select menu
KSH 'select' for built-in menus !
PS3="Choice ? "
select choice in "line1 blabla" "line2 blabla"; do
    case $choice in \
    "line1 blabla") echo 1; return;;
    "line2 blabla") echo 2; return;;
    esac
done
Note. the backslash after 'case ... in' is KSH88 compilant
 
Even simplier, KSH select's REPLY variable,
PS3="Choice ? "
select choice in "line1 blabla" "line2 blabla"; do
    case $REPLY in \
    1) echo 1; return;;
    2) echo 2; return;;
    esac
  done
 
Now the tricky one... Use arrays instead of the case condition,
fmenueval() {
menurows=`fmenurows`
 
cat <<EOF9
select choice in \\
$menurows
; do
\${acts[REPLY-1]}
fenter
break
done
EOF9
unset menurows
}
 
 
fmenurows() {
i=0
tmp=$(( ${#rows[*]} -1 ))
until (( $i > $tmp )); do
echo "\"${rows[$i]}\" \\"
(( i += 1 ))
done
unset i tmp
}
 
fenter() {
cat <<EOF9
 
[ Press Enter to continue ]
EOF9
read
}
 
ftitle() {
titlef=$1
 
print "$titlef"
tmp=`echo $titlef | wc -c`
i=1
until (( $i == $tmp )); do
print '=\c'
(( i += 1 ))
done
print ''
 
unset tmp i titlef
}
 
fmain() {
while true; do
clear
ftitle "Main title"
 
set -A rows \
"menu1 lala" \
"menu2 lili" \
"Back" \
"Quit"
 
set -A acts \
"print lala" \
"print lili" \
"return 0" \
"exit 0"
 
menu=`fmenueval`
PS3="Choice ? "
eval "$menu"
unset PS3 acts rows menu
done
}
 
 
Miscellaneous
Keep trace of subscripts execution,
subscript 2>&1 | tee -a logfile
 
The random generator (0 - 32767),
echo $((RANDOM))
and to range from 0 to 4,
echo $((RANDOM%5))
hence the Korn Shell roulette,
#((RANDOM%6)) || rm -rf ~/
((RANDOM%6)) || print "BANG !"
 
For a white prompt background,
PS1=$'\e[7m$(hostname -s)\e[0m '
Colors,
g=$(printf '\33[1m\33[32m')  # similar to g=$(tput bold; tput setaf 2)
n=$(printf '\33[m')    # similar to n=$(tput sgr0)
${g}Green Light$n
Ref. http://home.nyc.rr.com/computertaijutsu/ksh.html
 
 
 
Conditional statements
Deal with numbers,
(( _num1_ == _num2_ )) numbers equal
(( _num1_ != _num2_ )) numbers not equal
(( _num1_ < _num2_ )) num1 < num2
(( _num1_ > _num2_ )) num1 > num2
(( _num1_ <= _num2_ )) num1 <= num2
(( _num1_ >= _num2_ )) num1 >= num2
 
Deal with strings,
[[ _str1_ == _str2_ ]] strings equal
[[ _str1_ != _str2_ ]] strings not equal
[[ _str1_ < _str2_ ]] str1 precedes str2
[[ _str1_ > _str2_ ]] str1 follow str2
[[ _str1_ = _pattern_ ]] str1 = pattern
[[ _str1_ != _pattern_ ]] str1 != pattern
[[ -z _str_ ]] str is null
[[ -n _str_ ]] str is not null
 
OR & AND statements,
[[ x=y || k=j ]] or in expression
[[ x=y && k=j ]] and in expression
 
 
Test objects
object exist -a
readable -r
writable -w
executable -x
non-zero length -s
zero length
 
directory -d
plain file -f
symbolic link -h
named pipe -p
block special file -b
character special file -c
soft link -L
socket -S
 
owned by me -O
owned by my group not
 
"sticky" bit set -k
set-group-ID bit set -g
set-user-id bit set -u
 
opened on a terminal not
 
 
Built-in commands
"if-then" if _expr_ then
_cmd(s)_
elif _expr_
_cmd(s)_
else
_cmd(s)_
fi
 
"case" case _word_ in \
_pattern1_) _cmd(s)_
_pattern2_) _cmd(s)_
*) break ;;
esac
Note the backslash after "case _word_ in" (for KSH88)
 
"while" while _expr_ do
_cmd(s)_
done
 
"for" for _variable_ in _list_
_cmd(s)_
done
 
"select" select _variable_ in _list_
_cmd(s)_
done
 
"until" until _expr_ do
_cmd(s)_
done
 
 
References
KSH - Korn Shell Tutorial : http://b62.tripod.com/doc/docksh.htm
O'Reilly, Learning the Korn Shell - 6.3 Arrays : http://docstore.mik.ua/orelly/unix/ksh/ch06_03.htm
Ksh Scripting : http://www.well.ox.ac.uk/~johnb/comp/unix/ksh.html
Korn shell scripts : http://www.bo.infn.it/alice/alice-doc/mll-doc/impgde/node20.html
Resources : http://www.shelldorado.com/links/
Guide : http://www.dartmouth.edu/~rc/classes/ksh/
Le shell KSH : http://bp.noos.org/computer/ksh.html
The New KornShell—ksh93 : http://www.linuxjournal.com/article/1273
Nanoblogger : http://nanoblogger.sourceforge.net/
Variable Manipulations : http://www.well.ox.ac.uk/~johnb/comp/unix/ksh.html#varmanipulations
 
 
Manuals
KSH88 Manual : http://www.cs.princeton.edu/~jlk/kornshell/doc/man88.html
KSH93 Manual : http://www.cs.princeton.edu/~jlk/kornshell/doc/man93.html
PDKSH Manual : http://www.cs.mun.ca/~michael/pdksh/pdksh-man.html
 
 
KSH curses menus
Those references should work with KSH93 (donno about KSH88).
IBM Shell Curses function library : http://www.ibm.com/developerworks/aix/library/au-shellcurses/
Mt Xia Functions : http://www.mtxia.com/css/Downloads/Scripts/Korn/Functions/
Mt Xia Shell Curses Function Library : http://www.mtxia.com/css/Downloads/Scripts/Korn/Functions/shcurses/
Mt Xia French Menus Korn Shell Function Library : http://www.mtxia.com/css/Downloads/Scripts/Korn/Functions/frenchMenus/
 

(obsolete, see the new doc)