Подтвердить что ты не робот

Bash: Как создать функцию из переменной?

Как создать функцию с именем из переменной? Я хочу написать шаблон script, который определяет функцию, названную после имени файла script. Что-то вроде этого (что, конечно, не работает):

#!/bin/bash
bname="$(basename $0)" # filename of the script itself

someprefix_${bname}() { # function name created from $bname variable
    echo test
}

Итак, если имя файла script равно foo.sh, тогда он должен определить функцию с именем someprefix_foo, которая будет эхо-тест.

4b9b3361

Ответ 1

Вы можете использовать eval:

eval "someprefix_${bname}() { echo test; }"

Bash даже позволяет "." в именах функций:)

Ответ 2

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

Для вашего обзора:

source /dev/stdin <<EOF
function someprefix_${bname}()
{
     echo "test";
};
EOF

Ответ 3

Решения "eval и" source "работают в IFF, у вас нет ничего в функции, которую можно было бы оценить при создании времени, когда вы на самом деле хотите отложить до времени выполнения.

source /dev/stdin << EOF
badfunc () 
{
    echo $(date)
}
EOF

$ date;badfunc;sleep 10;date;badfunc
Tue Dec  1 12:34:26 EST 2015 ## badfunc output not current
Tue Dec  1 12:23:51 EST 2015
Tue Dec  1 12:34:36 EST 2015 ## and not changing
Tue Dec  1 12:23:51 EST 2015

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

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

tmpsh=$(mktemp)
echo "goodfunc ()" > $tmpsh
echo '{' >> $tmpsh
echo 'echo $(date)' >> $tmpsh
echo '}' >> $tmpsh
. $tmpsh
rm -f $tmpsh

а затем

$ date;goodfunc;sleep 10;date;goodfunc
Tue Dec 1 12:36:42 EST 2015 ## current
Tue Dec 1 12:36:42 EST 2015
Tue Dec 1 12:36:52 EST 2015 ## and advancing
Tue Dec 1 12:36:52 EST 2015

Надеюсь, это будет более полезным для людей. Наслаждайтесь.

Ответ 4

Я использую следующий синтаксис, который позволяет избежать /dev/stdin, но все же позволяет использовать heredocs:

eval "$(cat <<EOF
  $function_name() {
    commands go here
    but "\$you \$have \$to \$escape $variables"
  }
EOF
)"