我正在尝试比较两个以上变量的状态。用例是一个脚本,除其他选项外,它应该根据可用的可执行文件仅选择(或自动选择)几种“模式”中的一种。部分语法图是:
[ [--fzf,-f]|[--rofi,-r]|[--dmenu,-d] ]
Run Code Online (Sandbox Code Playgroud)
变量是基于命令参数的存在而定义的,因此,例如,如果在命令行参数中找到--fzf或,则-f关联的fzf变量设置为“1”,表示用户希望在其中运行脚本,因为缺少更好的条款,fzf mode。
下面的&&运算符语句解决了在命令行中找不到任何命令参数时会发生的情况。基本上,如果未选择“模式”,则脚本将自动选择一种且仅一种模式以分层方式使用。
下面的||operator 语句应该解决如果(由用户)选择了一种模式,但未找到底层可执行文件时会发生什么。
这是 && 运算符的原始版本:
[ [--fzf,-f]|[--rofi,-r]|[--dmenu,-d] ]
Run Code Online (Sandbox Code Playgroud)
到
if [[ $fzf = 0 && $rofi = 0 ]]; then
if command_exists fzf; then
fzf=1
elif command_exists rofi; then
rofi=1
fi
fi
Run Code Online (Sandbox Code Playgroud)
最后,这里是 || 的原文 操作员:
if [[ $fzf = 0 && $rofi = 0 && $dmenu = 0 ]]; then
if command_exists fzf; then
fzf=1
elif command_exists rofi; then
rofi=1
elif command_exists dmenu; then
dmenu=1
fi
fi
Run Code Online (Sandbox Code Playgroud)
到
if [[ $rofi = 1 || $fzf = 0 ]]; then
command_exists rofi || die "Could not find rofi in \$PATH"
menu="$rofi_cmd"
elif [[ $fzf = 1 || $rofi = 0 ]]; then
command_exists fzf || die "Could not find fzf in \$PATH"
menu="$fzf_cmd"
else
die "Could not find either fzf or rofi in \$PATH"
fi
Run Code Online (Sandbox Code Playgroud)
这似乎没有引发任何错误,但我怀疑这既不是正确的方法,也可能无法按预期工作(因为它在使用-x和查看输出时似乎报告了错误的值)。
我所知道的岗位,如这一个,但我没有(还)发现的例子有两个以上的变量(如我尝试了上述这样做)。
以上原始部分取自此脚本。我基本上是在尝试添加对 的支持,dmenu因为它只支持rofi和fzf(如上所示)。
这里是完整的修改脚本。它需要password-store作为依赖项。
我正在使用 Bash 5.0.3。
我如何使用 && 和 || 具有两个以上变量的运算符正确吗?
如果用户只应该选择众多中的一个,我只会使用一个变量来保存选择,删除每个选项的变量。无论如何,我们并不真正关心所有的组合,我们只想要三个中的一个,另一个是“未设置/默认”。
所以:
#!/bin/sh
cmd= # empty value for default
case "$1" in
--rofi|-r) cmd=rofi ;;
--fzf|-f) cmd=fzf ;;
--dmenu|-d) cmd=dmenu ;;
esac
if [ -z "$cmd" ]; then
echo "no command set, looking for default"
if command_exists fzf; then
cmd=fzf
elif
...
fi
fi
echo "running with command $cmd"
# actually do something
Run Code Online (Sandbox Code Playgroud)
在这里,选择的模式存储在cmd. 我实际上甚至没有给用户提供两个命令的可能性,只有第一个参数被读取以获取标志。现在,如果你使用getoptor getopts,那并没有真正成功,但我们可以在设置之前检查模式是否已经设置(再次)。
#!/bin/sh
error_if_cmd_set() {
if [ -n "$1" ]; then
echo "command already set"
exit 1
fi
}
cmd=
for arg in "$@"; do
case "$1" in
--rofi|-r) error_if_cmd_set "$cmd"; cmd=rofi ;;
--fzf|-f) error_if_cmd_set "$cmd"; cmd=fzf ;;
--dmenu|-d) error_if_cmd_set "$cmd"; cmd=dmenu ;;
esac
done
# ...
echo "using command $cmd"
Run Code Online (Sandbox Code Playgroud)