开发者

Case statements evaluate to strings

I've caught the functional programming bug, so naturally nothing is goo开发者_开发知识库d enough for me anymore. ;)

So, in bash one could write:

case $status in
  "foo") status="bar" ;;
  "baz") status="buh" ;;
   *) status=$status ;;
esac

but I'm afraid of typos, so I'd prefer to write:

status=case $status in
  "foo") "bar" ;;
  "baz") "buh" ;;
  *) $status ;;
esac

The second form is invalid since the case evaluates to the exit code of the last executed command, which is not at all what I'm looking for.

Are there easy hacks to achieving what I am looking for?


If you're sure status will only be one line, you could do something like this with sed:

status=$(echo "$status" | sed -e 's:^foo$:bar:' -e 's:^baz$:buh:')

You may also be able to get something to work with bash's built-in substitution. This almost works (I don't know of any way to get exact matching only):

status=${status/foo/bar}
status=${status/baz/buh}

If your goal is just to be more "functional" (and not to make your code more typo-proof), you could do this:

status=$(
  case "$status" in
    ("foo") echo "bar" ;;
    ("baz") echo "buh" ;;
    (*) echo "$status" ;;
  esac)

Though honestly, bash is probably one of the worst languages to try and be functional in. It was really designed with a more imperative mindset, as illustrated by the fact that you can't easily compose expressions. See in the second code snippet how I had to break it into two separate statements? If bash were designed to be functional you'd be able to write something like this instead:

status=${{status/baz/buh}/foo/bar}

But that does not work.

I'd suggest only using bash for simpler scripts, and for more complicated stuff use something like Python or Ruby. They'll let you write more functional code without having to constantly wrestle with the language.


status="baz"
status=$(case $status in
  "foo") echo "bar" ;;
  "baz") echo "buh" ;;
  *) echo $status ;;
esac)
echo "status: $status"

output

$ ./shell.sh
status: buh


Bash 4 has associative arrays:

# setup
unset vals i
indices=(foo baz)
val=(bar buh)
declare -A vals             # associative
for index in ${indices[@]}
do
    vals[$index]=${val[i++]}
done

$ # demos
$ status="foo"
$ status=${vals:-$status}
$ echo $status
bar
$ status="not found"
$ status=${vals:-$status}
$ echo $status
not found
0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜