Как использовать операторы && и || операторы с более чем двумя переменными правильно?

Вы можете повторить имя, если grep не совпадает:

$ for i in cindrella daniel polo; do grep -q "$i" test.txt || echo "$i"; done
cindrella
daniel

-qтихий режим, выход после обнаружения любого совпадения

0
24.09.2020, 04:54
2 ответа

Честно говоря, я не знаю, что вы пытаетесь сделать с этими чеками. Если вам нужно проверить, доступна ли хотя бы одна из этих программ:

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

4
18.03.2021, 23:02

Если предполагается, что пользователь должен выбрать только одну из многих, я бы просто использовал одну переменную для сохранения выбора, отбрасывая переменные опции per -. В любом случае, нас не интересуют все комбинации, нам просто нужен один вариант из трех, а другой — «не установлен/по умолчанию».

Так:

#!/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"
5
18.03.2021, 23:02

Теги

Похожие вопросы