Как передать комбинированную команду в качестве параметра функции - PullRequest
0 голосов
/ 06 ноября 2019
checkcommand() {
   $1
}

checkcommand "which git || apt install git"

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

Ответы [ 3 ]

3 голосов
/ 06 ноября 2019

Вам просто нужно обернуть строку в eval ключевое слово

checkcommand() {
  eval "$1"
}

Цитирование ("$1", а не $1) гарантирует, что точная строка будет оценена как код;в противном случае оно разбивается на слова, каждое слово раскрывается как глобус, а полученные слова объединяются обратно;если вам повезло, это не изменило смысл вашей команды - но не всегда можно повезти, поэтому всегда лучше процитировать ваши расширения, если вы явно не знаете почему вы их покидаетебез кавычек в любом противоположном случае.

См. справочную страницу для POSIX eval.

1 голос
/ 06 ноября 2019

Не пытайтесь запустить одну строку, как если бы это была команда - вместо этого передайте явный список аргументов . Это дает вам гибкость выбора того режима работы, который вам подходит:

## first, define your function as:
checkcommand() {
   "$@"   # expands to "$1" "$2" "$3" ...etc, for all arguments that actually exist
}

## then, you can pass it any simple command...
type git || checkcommand apt install git

## ...or you can use it with eval...
checkcommand eval "type git || apt install git"

## ...or you can pass it a function with an argument list...
installPkg() { for pkg; do type "$pkg" || apt install "$pkg"; done; }
checkcommand installPkg git tig gcc

## ...or you can tell it to invoke a whole new shell instance...
checkcommand sh -c 'type git || apt install git'

Для подробного описания того, почему обработка строки как команды обречена на неудачу (в достаточно сложных случаях использования),см. BashFAQ # 50 .

0 голосов
/ 06 ноября 2019

Я собираюсь предложить альтернативный подход, я признаю, что не отвечает напрямую.

Я предлагаю этот подход, потому что он может быть сложным для передачи команды и аргументов и агрегированных групп команд и аргументов другомувыполняемая и проверяемая функция.

Вместо этого проще выполнить команды и затем запустить функцию проверки, например,

check_error()
{
    lasterr=$?
    msg="$*"

    if [ "${lasterr}X" != "0X" ];
    then
        echo "command failed, errcode ${lasterr}, $msg"
        exit 1
    fi
}

...

which git || apt install git
check_error "git failed"

... обратите внимание, что функция check_error должнабыть следующим оператором немедленно после команд, которые вы хотите проверить.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...