【问题标题】:Case statements evaluate to strings案例语句评估为字符串
【发布时间】:2011-01-18 00:36:12
【问题描述】:

我发现了函数式编程错误,所以自然对我来说没有什么是足够好的了。 ;)

所以,在 bash 中可以这样写:

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

但我怕错别字,所以我宁愿写:

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

第二种形式是无效的,因为 case 评估为最后执行的命令的退出代码,这根本不是我想要的。

是否有简单的技巧来实现我我正在寻找的东西?

【问题讨论】:

  • 你只是想写一个函数吗?
  • 如果你害怕拼写错误,请在程序开头使用set -u。

标签: bash functional-programming notation case-statement


【解决方案1】:

如果你确定 status 只会是一行,你可以用 sed 做这样的事情:

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

您还可以使用 bash 的内置替换来获得一些东西。这几乎有效(我不知道有什么方法可以只获得精确匹配):

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

如果您的目标只是更“实用”(而不是让您的代码更防错字),您可以这样做:

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

老实说,bash 可能是最差劲的语言之一。它实际上是用一种更加命令式的思维方式设计的,正如你不能轻易地编写表达式的事实所说明的那样。在第二个代码 sn-p 中看到我如何将它分成两个单独的语句?如果 bash 被设计成功能性的,你就可以写这样的东西:

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

但这不行得通。

我建议只对更简单的脚本使用 bash,而对于更复杂的东西,使用 Python 或 Ruby 之类的东西。它们可以让您编写更多功能性代码,而无需不断与语言搏斗。

【讨论】:

  • zsh 将让您像上一个示例一样进行嵌套参数扩展。
  • @mbac32768 据我所知,我确实回答了您的问题,实际上是三遍。如果您不同意,也许您需要重新提出您的问题,或者您至少可以解释为什么这些解决方案不适合您。当有人努力帮助你时变得尖酸刻薄是有点蹩脚的。
  • 我将他对您问题的回答读作“不,这就是为什么和其他一些选择”。很好的答案。
  • @mbac32768 你没问过如何用函数式的方式写那个switch语句吗?我不是给你展示了三个选择吗?至于指出您不应该尝试在 bash 中进行功能性编程,当问题表明存在更大问题时,Stack Overflow 上的答案通常会退后一步指出问题。如果发现您正在沿着花园小径散步会伤害您的感受,那么也许您不应该在 Stack Overflow 上提问,或者您可以学习处理建设性的批评。
  • @mbac32768 status=$(...echo...) 怎么不能回答你的问题?你正在寻找一个黑客来做到这一点,你在这里。坦率地说,你在这里是个混蛋(或者是 8 年前)。
【解决方案2】:
status="baz"
status=$(case $status in
  "foo") echo "bar" ;;
  "baz") echo "buh" ;;
  *) echo $status ;;
esac)
echo "status: $status"

输出

$ ./shell.sh
status: buh

【讨论】:

  • 这是我发布的第三个 sn-p,但有语法错误。 ($(...) 中的 close parens 混淆了 bash,因此您需要在每个 case 上使用可选的 open paren。)
  • 混淆 bash 是什么意思?
  • 好的,我猜你正在使用 bash
  • 是的,我仍在使用 3.x(我使用的是 Ubuntu 的 LTS 版本)。有趣的是 4 可以解析。
【解决方案3】:

Bash 4 有关联数组:

# 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

【讨论】:

  • 这真的是你应该如何在 bash4 中初始化关联数组吗?
  • @Charles:对于这个演示来说,这是一种权宜之计。例如,我本可以完成for index in foo baz,而不是使用数组。或进行直接批量分配或从文件中读取。你特别想问的是什么?
猜你喜欢
  • 1970-01-01
  • 2021-09-25
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2017-04-08
相关资源
最近更新 更多