我试着比较两个以上变量的状态。用例是一个脚本,在其他选项中,应该根据可用的可执行文件选择(或自动选择)几种“模式”中的一种。部分语法图是:
[ [--fzf,-f]|[--rofi,-r]|[--dmenu,-d] ]这些变量是基于命令参数的存在而定义的,因此,例如,如果在命令行参数中找到--fzf或-f,则关联的fzf变量被设置为"1“,表示用户希望在fzf mode中运行脚本,因为没有更好的条件。
下面的&&操作符语句解决了如果在命令行中找不到任何命令参数会发生什么。基本上,如果没有选择“模式”,那么脚本将自动选择一个模式,并且只有一个模式,以分层的方式使用。
下面的||操作符语句应该解决如果选择模式(由用户选择),但找不到底层可执行文件时会发生什么情况。
以下是&&运算符的原始版本:
if [[ $fzf = 0 && $rofi = 0 ]]; then
if command_exists fzf; then
fzf=1
elif command_exists rofi; then
rofi=1
fi
fi至
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最后,在这里,用原值表示的连取操作符:
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至
if [[ $rofi = 1 || $fzf = 0 || $dmenu = 0 ]]; then
command_exists rofi || die "Could not find rofi in \$PATH"
menu="$rofi_cmd"
elif [[ $fzf = 1 || $rofi = 0 || $dmenu = 0 ]]; then
command_exists fzf || die "Could not find fzf in \$PATH"
menu="$fzf_cmd"
elif [[ $dmenu = 1 || $rofi = 0 || $fzf = 0 ]]; then
command_exists dmenu || die "Could not find dmenu in \$PATH"
menu="$dmenu_cmd"
else
die "Could not find either fzf or rofi or dmenu in \$PATH"
fi这似乎不会抛出任何错误,但我怀疑这不是正确的方法,而且可能不像预期的那样工作(因为在使用-x并看到它的输出时,它似乎报告了错误的值)。
我知道有像这 1这样的帖子,但是我还没有(还)找到有两个以上变量的例子(就像我在上面做的那样)。
以上部分是从这脚本中提取的。我基本上是想添加对dmenu的支持,因为它只支持rofi和fzf (如上面所示)。
这里是完全修改的脚本。它需要password-store作为依赖项。
我用的是Bash 5.0.3。
如何正确地使用具有多个变量的&和_
发布于 2020-09-23 20:49:00
||和&&运营者运作良好。在翻译脚本的方式上存在问题,但是,尽管一再要求逻辑上的澄清,但没有提供任何问题。因此,我根据我如何理解复制的脚本工作来补充这个问题。
一件有趣的事情是,问题中没有张贴的部分脚本被翻译错了:
if [[ $fzf = 1 && $rofi = 1 && $dmenu = 1 ]]; then
die 'Either --fzf,-f or --rofi,-r or --dmenu,-d must be given, not more than one'
fi最重要的是,在快速审查之后才能说出的意图是,这一声明应该更符合以下几点:
if [[ $(( $fzf + $rofi + $dmenu )) > 1 ]]; then
die 'Either --fzf,-f or --rofi,-r or --dmenu,-d must be given, not more than one'
fi可能还有其他问题。你提供所有相关信息是非常重要的。
发布于 2020-09-23 21:05:56
如果用户应该只选择其中一个,我只需要使用一个变量来保存选择,删除每个选项变量。无论如何,我们并不真正关心所有的组合,我们只想选择三个中的一个,而另一个选择是"unset/default“。
所以:
#!/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在这里,选择的模式存储在cmd中。实际上,我甚至没有给用户提供两个命令的可能性,只为标志读取第一个参数。现在,如果您使用getopt或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"发布于 2020-09-23 18:55:19
我真的不知道你想用那些支票做什么。如果您需要检查这些程序中至少有一个可用:
programs=(fzf rofi dmenu)
available=()
for prog in "${programs[@]}"; do
location=$(type -P $prog) && available+=("$location")
done
(( ${#available[@]} == 0 )) && die "none of ${programs[*] are available"
# what is your logic for choosing one if multiple are available?
menu=${available[0]}根据您的评论,将更多的工作推入案例分支会更清晰:
fzf_exists=0
rofi_exists=0
dmenu_exists=0
# reorder these if you want: the _last_ one to succeed is the default
if command_exists dmenu; then
dmenu_exists=1
menu_default=$dmenu_cmd
fi
if command_exists rofi; then
rofi_exists=1
menu_default=$rofi_cmd
fi
if command_exists fzf; then
fzf_exists=1
menu_default=$fzf_cmd
fi
if [[ -z $menu_default ]]; then
die "none of fzf, rofi, dmenu are available"
fi
while true; do
case "$1" in
-f|--fzf)
(( fzf_exists )) || die "fzf is not available"
[[ -n $menu ]] && die "choose only one of fzf/rofi/dmenu"
menu=$fzf_cmd
shift
;;
-r|--rofi)
(( rofi_exists )) || die "rofi is not available"
[[ -n $menu ]] && die "choose only one of fzf/rofi/dmenu"
menu=$rofi_cmd
shift
;;
-d|--dmenu)
(( dmenu_exists )) || die "dmenu is not available"
[[ -n $menu ]] && die "choose only one of fzf/rofi/dmenu"
menu=$dmenu_cmd
shift
;;
# ...
esac
done
: ${menu:=$menu_default}注意,command_exists函数应该是return 1而不是exit 1
https://unix.stackexchange.com/questions/611001
复制相似问题