bug-gnulib
[Top][All Lists]
Advanced

[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
}




reply via email to

[Prev in Thread] Current Thread [Next in Thread]