【问题标题】:sh conditionally pass an option to commandsh 有条件地将选项传递给命令
【发布时间】:2018-07-21 11:42:07
【问题描述】:

我想做这样的事情:

#!/bin/sh

[ -f "/tmp/nodes" ]
[[ $? -eq 0 ]] && VAL=$? ||

geth --datadir /root/.ethereum \
     ${VAL+"--nodekey \"/root/nodekey.txt\""} \     
     --networkid 1999 \
     --rpc \
     --rpcaddr "0.0.0.0" \

如果文件/tmp/nodes 存在,我希望通过选项--nodekey "/root/nodekey.txt"。怎么能比 if 用两个几乎相同的命令更优雅地完成呢?

--编辑--

这是迄今为止我能做到的最好的工作:

if [ $VAL -eq 0 ]; then
    /geth --datadir /root/.ethereum \
          --nodekey "/root/nodekey.txt" \
          # No dice
          # Would be nice if this worked so I didn't need the if
          # ${VAL+ --nodekey "/root/nodekey.txt" } \
          --networkid 1999 \
          --rpc \
          --rpcaddr "0.0.0.0" 
else
    /geth --datadir /root/.ethereum \
          --networkid 1999 \
          --rpc \
          --rpcaddr "0.0.0.0" \
fi

这是文件中的另一行,工作正常:

ENODE_URL=$(/geth --datadir /root/.ethereum ${VAL+ --nodekey "/root/nodekey.txt"} --exec "${JS}" console 2>/dev/null | sed -e 's/^"\(.*\)"$/\1/')

【问题讨论】:

  • 是的,决定是 sh 还是 bash。 Bashism 只有当你以bash yourscript.sh 调用它时才有效,而不是./yourscript.sh"。
  • sh 我显然不是 ba(sh) 脚本编写者,所以我有一个坏习惯,称它们为同一个东西。
  • 顺便说一句——全大写的名称用于对操作系统和外壳有意义的变量,而所有其他名称都保留给应用程序使用。请参阅pubs.opengroup.org/onlinepubs/9699919799/basedefs/…,第四段——因此,不要为自己的变量使用全大写名称,以避免错误地覆盖系统或 shell 定义的变量。
  • 如果您能向我们证明${VAL+ --nodekey "/root/nodekey.txt" } 不起作用 会很有帮助。你能提供一个minimal reproducible example 其他人可以运行的代码来查看它不工作吗?
  • 请注意,您的代码 [ $VAL -eq 0 ]${VAL+ ...} 逻辑完全不同:前者检查数值是否等于 0,后者检查值是否已设置(甚至是否设置为非-空字符串,但是否设置完全;如果你运行VAL=,即使这样也会设置它,因此会导致${var+foo}扩展为foo

标签: bash shell sh options


【解决方案1】:

这里有一个 bashism,但它是 [[ $? -eq 0 ]],因为 [[ 是 bash 采用的 ksh 扩展。在这里使用$? 毫无意义,因为您可以直接根据test -f 是否成功执行分配:

touch /tmp/nodes  # set us up for the truthy path
if test -f /tmp/nodes; then tmp_nodes_exists=1; else unset tmp_nodes_exists; fi
printf '%s\n' /tmp/nodes ${tmp_nodes_exists+"REALLY EXISTS" "(yes, really)"}

...正确地作为输出发出(与dash 一起运行,也许是最常见的最小/bin/sh 解释器):

/tmp/nodes
REALLY EXISTS
(yes, really)

相比之下,为了证明另一条路径应该失败:

rm -f -- /tmp/nodes  # set us up for the falsey path
if test -f /tmp/nodes; then tmp_nodes_exists=1; else unset tmp_nodes_exists; fi
printf '%s\n' /tmp/nodes ${tmp_nodes_exists+"REALLY EXISTS" "(yes, really)"}

仅作为输出发射:

/tmp/nodes

【讨论】:

    猜你喜欢
    • 2022-11-14
    • 1970-01-01
    • 2015-02-15
    • 1970-01-01
    • 2016-11-05
    • 2023-03-23
    • 1970-01-01
    • 2021-04-19
    相关资源
    最近更新 更多