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


119

我有一个具有某些功能的脚本。

我可以直接从命令行运行功能之一吗?

像这样吗

myScript.sh func()

Answers:


66

如果脚本仅定义函数,而没有执行其他任何操作,则可以先使用sourceor .命令在当前shell的上下文中执行脚本,然后简单地调用函数。请参阅help source以获取更多信息。


1
此方法的唯一问题是,如果exit在函数中使用它,则在执行函数后它将关闭终端。有没有办法解决?@SvenMarnach
user1527227'9

@ user1527227:在这种情况下,如果您已控制了shell脚本,请继续下一个答案。否则,您可以先调用一个交互式子外壳程序(只需输入bash),并且exit只会终止该子外壳程序,而不会终止您的终端。
Sven Marnach 2014年

238

好吧,尽管其他答案是正确的-您当然可以做其他事情:如果您有权访问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

16
"$@"在大多数情况下使用。$@在某些情况下不安全。
fumiyas 2015年

1
如何运行多个功能?例如我可以跑步bash test.sh testA testB吗?
Jeff Pang

这也需要用[ ! -z "$1" ]其他方式包装,否则源代码将在某些bash版本中引发else语句
JackLeo 18'S9 3'18

我一直在寻找这个神奇的“ $ @”变量,以使用在文件上调用的任何函数,谢谢@sdaau!
贾斯汀·哈蒙德

36

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

. ./myScript.sh && function_name

1
您也可以简单地使用源代码。如上所示-源myScript.sh && function_name
stolen_leaves

17

简要地,没有。

您可以使用source(将脚本中的所有函数导入到您的环境中help source有关详细信息)将然后可以调用它们。这也具有执行脚本的效果,因此请注意。

无法从Shell脚本调用函数,就好像它是共享库一样。


1
我认为这应该作为适当的答案。我试图做一些与OP想要的类似的事情,但是shell脚本根本不是为“干净的OOP开发”(IMHO)设计的。
Dan L

4

使用 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

1

编辑:警告-似乎这并非在所有情况下都有效,但在许多公共脚本上都能很好地工作。

如果您有一个名为“ control”的bash脚本,并且其中包含一个名为“ build”的函数:

function build() { 
  ... 
}

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

./control build

如果在另一个文件夹中,则可以:

another_folder/control build

如果您的文件名为“ control.sh”,则将相应地使函数可调用,如下所示:

./control.sh build

1
对于我来说,这在交互式shell中不起作用。但这有效:. ./control.sh && build
saulius2 '19

1

我有一种情况,我需要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


0

您可以从命令行参数调用函数,如下所示

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

一旦函数结束,将$ 1接受参数,就可以说上述代码保存在fun.sh中,以运行函数./fun.sh irfan&./fun.sh config


0

解决了帖子,但我想提及我的首选解决方案。即,定义一个通用的单行脚本eval_func.sh

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

然后通过以下命令在任何脚本中调用任何函数:

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

我在接受的解决方案中遇到的一个问题是,在另一个脚本中采购包含函数的脚本时,后者的参数将由前者评估,从而导致错误。

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.