如何在命令行中从脚本运行函数?

我有一个脚本,有一些功能。

我可以直接从命令行运行其中一个函数吗?

像这样吗?

myScript.sh func()
228621 次浏览

如果脚本只定义函数而不执行其他操作,那么您可以首先使用 source.命令在当前 shell 的上下文中执行脚本,然后简单地调用函数。有关更多信息,请参见 help source

下面的命令首先在上下文中注册函数,然后调用它:

. ./myScript.sh && function_name

简单地说,没有。

您可以使用 source(详细信息为 help source)将脚本中的所有函数导入到您的环境中,然后您可以调用它们。这也有执行脚本的效果,所以要小心。

不能像从共享库那样从 shell 脚本调用函数。

好吧,虽然其他答案是正确的——你当然可以做一些其他的事情: 如果你可以访问 bash 脚本,你可以修改它,并简单地放置在最后的特殊参数 "$@"-这将扩展到你指定的命令行的参数,因为它是“单独的”,shell 将尝试调用他们逐字逐句; 在这里,你可以指定的函数名作为第一个参数。例如:

$ cat test.sh
testA() {
echo "TEST A $1";
}


testB() {
echo "TEST B $2";
}


"$@"




$ bash test.sh
$ bash test.sh testA
TEST A
$ bash test.sh testA arg1 arg2
TEST A arg1
$ bash test.sh testB arg1 arg2
TEST B arg2

对于波兰语,您可以首先验证命令是否存在并且是一个函数:

# Check if the function exists (bash specific)
if declare -f "$1" > /dev/null
then
# call arguments verbatim
"$@"
else
# Show a helpful error
echo "'$1' is not a known function name" >&2
exit 1
fi

编辑: 警告——似乎这并不适用于所有情况,但适用于许多公共脚本。

如果你有一个名为“ control”的 bash 脚本,其中有一个名为“ build”的函数:

function build() {
...
}

然后你可以这样调用它(从它所在的目录) :

./control build

如果它在另一个文件夹里,那就是:

another_folder/control build

如果您的文件名为“ control. sh”,那么函数就可以像下面这样调用:

./control.sh build

我遇到过这样的情况: 我需要一个 bash 脚本中的函数,而这个函数之前是不能执行的(比如 source) ,而 @$的问题在于 myScript.sh 会运行两次,看起来... ... 所以我想出了用 sed 取出这个函数的办法:

sed -n "/^func ()/,/^}/p" myScript.sh

为了在我需要它的时候执行它,我把它放在一个文件中并使用 source:

sed -n "/^func ()/,/^}/p" myScript.sh > func.sh; source func.sh; rm func.sh

您可以像下面这样从命令行参数调用 function

function irfan() {
echo "Irfan khan"
date
hostname
}
function config() {
ifconfig
echo "hey"
}
$1

一旦定义了函数,将 $1放在最后,以接受要调用的函数的参数。 假设上面的代码保存在 fun.sh 中。现在可以调用类似。/fun.sh irfan & .在命令行中配置/fun.sh。

使用 case

#!/bin/bash


fun1 () {
echo "run function1"
[[ "$@" ]] && echo "options: $@"
}


fun2 () {
echo "run function2"
[[ "$@" ]] && echo "options: $@"
}


case $1 in
fun1) "$@"; exit;;
fun2) "$@"; exit;;
esac


fun1
fun2

这个脚本将运行 fun1和 fun2函数,但是如果使用选项启动它 Fun1或 fun2它将只运行带有 args (如果提供的话)的给定函数并退出。 用法

$ ./test
run function1
run function2


$ ./test fun2 a b c
run function2
options: a b c

解决后,但我想提到我的首选解决方案。即,定义一个通用的一行程序脚本 eval_func.sh:

#!/bin/bash
source $1 && shift && "@a"

然后通过以下方式调用任何脚本中的任何函数:

./eval_func.sh <any script> <any function> <any args>...

我在使用公认的解决方案时遇到的一个问题是,当在另一个脚本中提供包含函数的脚本时,后者的参数将由前者计算,从而导致错误。

这里的其他答案很好,非常感谢,但是我通常不希望 source脚本 在治疗过程中(它读取并执行当前 shell 中的文件) 或者直接修改它。

我发现编写一两行‘ bootstrap’文件并运行它更方便。使得测试主脚本更加容易,不会对 shell 会话产生副作用,并且作为奖励,您可以加载模拟其他环境进行测试的内容。例如..。

# breakfast.sh
make_donuts() {
echo 'donuts!'
}


make_bagels() {
echo 'bagels!'
}
# bootstrap.sh
source 'breakfast.sh'


make_donuts

现在只需要运行 ./bootstrap.sh. 相同的思想适用于 python、 ruby 或任何脚本。

为什么有用?比方说,由于某些原因,你的生活变得复杂,你的脚本可能会发现自己处于不同的环境中,呈现不同的状态。例如,您的终端会话,或者云提供商的新东西。您还希望使用简单的方法在终端中测试云计算。不用担心,您的引导程序可以为您加载基本状态。

# breakfast.sh
# Now it has to do slightly different things
# depending on where the script lives!


make_donuts() {
if [[ $AWS_ENV_VAR ]]
then
echo '/donuts'
elif [[ $AZURE_ENV_VAR ]]
then
echo '\donuts'
else
echo '/keto_diet'
fi
}

如果你让你的引导程序带一个参数,你可以加载不同的状态让你的函数去咀嚼,在 shell 会话中仍然只有一行:

# bootstrap.sh
source 'breakfast.sh'


case $1 in
AWS)
AWS_ENV_VAR="arn::mumbo:jumbo:12345"
;;
AZURE)
AZURE_ENV_VAR="cloud::woo:_impress"
;;
esac


make_donuts # You could use $2 here to name the function you wanna, but careful if evaluating directly.

在终端会话中,您刚刚输入: ./bootstrap.sh AWS 结果: # /donuts