[Top][All Lists]
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
ksh's select, almost, in portable shell
From: |
Peter Seebach |
Subject: |
ksh's select, almost, in portable shell |
Date: |
Wed, 17 Sep 2008 13:07:19 -0500 |
This came from a pair of sources; my work on portable shell, and the discovery
that glibc's tzselect "requires ksh".
Originally, I thought "there's no way you could implement select in a shell
which doesn't have it, because it's a control structure". And indeed, you
can't.
But you can implement a shell function such that
while func_select var in args
do
done
is equivalent (nearly) to
select var in args
do
done
I enclose func_select below. Weaknesses:
1. Newline after prompt. (Solving this portably seemed like too much work.)
2. "in args" is not optional; it can't implicitly use address@hidden
So far as I can tell, this is basically solid. What'd I miss?
func_select () {
func_select_args=0
if expr "$1" : "^[_a-zA-Z][_a-zA-Z0-9]*$" > /dev/null; then
func_select_var=$1
else
echo >&2 "func_select: '$1' is not a valid variable name."
return 1
fi
shift 1
case $1 in
in) shift 1;;
*) echo >&2 "func_select: usage: func_select var in ... (you must provide
arguments)"; return 1;;
esac
case $# in
0) echo >&2 "func_select: usage: func_select var in ..."; return 1;;
esac
for func_select_arg
do
func_select_args=`expr $func_select_args + 1`
eval func_select_a_$func_select_args=\$func_select_arg
done
REPLY=""
while :
do
if test -z "$REPLY"; then
func_select_i=1
while test $func_select_i -le $func_select_args
do
eval echo "\"\$func_select_i) \$func_select_a_$func_select_i\""
func_select_i=`expr $func_select_i + 1`
done
fi
echo "${PS3-#? }"
if read REPLY; then
if test -n "${REPLY}"; then
if expr "$REPLY" : '^[1-9][0-9]*$' > /dev/null; then
if test "$REPLY" -ge 1 && test "$REPLY" -le $func_select_args; then
eval $func_select_var=\$func_select_a_$REPLY
else
eval $func_select_var=
fi
else
eval $func_select_var=
fi
return 0
fi
else
eval $func_select_var=
return 1
fi
done
}
- ksh's select, almost, in portable shell,
Peter Seebach <=