我可以从另一个 shell 脚本调用一个 shell 脚本的函数吗?
Posted
技术标签:
【中文标题】我可以从另一个 shell 脚本调用一个 shell 脚本的函数吗?【英文标题】:Can I call a function of a shell script from another shell script? 【发布时间】:2012-06-05 01:43:57 【问题描述】:我有 2 个 shell 脚本。
第二个shell脚本包含以下函数 second.sh
func1
func2
first.sh 将调用带有一些参数的第二个 shell 脚本和 将使用特定于该函数的一些其他参数调用 func1 和 func2。
这是我所说的例子
second.sh
val1=`echo $1`
val2=`echo $2`
function func1
fun=`echo $1`
book=`echo $2`
function func2
fun2=`echo $1`
book2=`echo $2`
first.sh
second.sh cricket football
func1 love horror
func2 ball mystery
我怎样才能实现它?
【问题讨论】:
重复 - ***.com/questions/8352851/…v=$(echo $1)
完全是多余的。只需写fun2=$1
。唯一的区别是$()
(或反引号)将删除尾随的换行符。
由于从 shell 脚本调用函数与命令行相比没有什么特别之处,所以这个问题可以简化为“如何调用 bash 函数?”
【参考方案1】:
像这样重构你的 second.sh
脚本:
func1
fun="$1"
book="$2"
printf "func=%s,book=%s\n" "$fun" "$book"
func2
fun2="$1"
book2="$2"
printf "func2=%s,book2=%s\n" "$fun2" "$book2"
然后像这样从脚本first.sh
调用这些函数:
source ./second.sh
func1 love horror
func2 ball mystery
输出:
func=love,book=horror
func2=ball,book2=mystery
【讨论】:
为避免意外的副作用,请注意source
命令实际上会运行作为参数传递的脚本。
@dvlcube 如果你能提出一个替代方案会更好。
这个答案很清楚很好。重要的是,***.com/a/42101141/852196 描述了一些人可能遇到的问题,并提供了一个优雅的通用解决方案。
@Alpha2k 我不确定是否有替代方案。这个想法是“小心你在源文件中放入的内容”【参考方案2】:
您不能直接调用另一个 shell 脚本中的函数。
您可以将您的函数定义移动到一个单独的文件中,然后使用.
命令将它们加载到您的脚本中,如下所示:
. /path/to/functions.sh
这会将functions.sh
解释为好像它的内容此时实际存在于您的文件中。这是实现 shell 函数共享库的常用机制。
【讨论】:
这与接受的答案不一样吗,因为.
是source
的别名?
好吧,我先回答了,所以从技术上讲,接受的答案与这个相同:)。此外,虽然source
在许多shell 中是.
的别名,但情况并非总是如此。例如,Debian 上提供/bin/sh
的dash
软件包没有source
命令。
source
命令在 Ubuntu @ajsharma 中不起作用。参考:source command not found in sh shell
太奇怪了,这条评论没有被评为最高?这是正确的 #!/bin/sh 语法,另一种只能在 bash 中使用。【参考方案3】:
问题
当前接受的答案仅在重要条件下有效。给定...
/foo/bar/first.sh
:
function func1
echo "Hello $1"
和
/foo/bar/second.sh
:
#!/bin/bash
source ./first.sh
func1 World
这只有在first.sh
是从first.sh
所在的同一目录中执行时才有效。 IE。如果shell当前工作路径为/foo
,则尝试运行命令
cd /foo
./bar/second.sh
打印错误:
/foo/bar/second.sh: line 4: func1: command not found
这是因为source ./first.sh
是相对于当前工作路径的,而不是脚本的路径。因此,一种解决方案可能是利用 subshell 并运行
(cd /foo/bar; ./second.sh)
更通用的解决方案
鉴于...
/foo/bar/first.sh
:
function func1
echo "Hello $1"
和
/foo/bar/second.sh
:
#!/bin/bash
source $(dirname "$0")/first.sh
func1 World
然后
cd /foo
./bar/second.sh
打印
Hello World
工作原理
$0
返回执行脚本的相对或绝对路径
dirname
返回目录的相对路径,$0 脚本所在的目录
$( dirname "$0" )
dirname "$0"
命令返回相对
执行脚本的目录路径,然后用作source
命令的参数
在“second.sh”中,/first.sh
只是附加了导入的shell脚本的名称
source
将指定文件的内容加载到当前
贝壳
【讨论】:
这正是我所需要的。非常感谢!【参考方案4】:second.sh
#!/bin/bash
function func1()
fun="$1"
book="$2"
echo "$fun, $book\n"
function func2()
fun2="$1"
book2="$2"
printf "$fun2, $book2\n"
first.sh
#!/bin/bash
source /absolute_path_to/second.sh
func1 love horror
func2 ball mystery
在使用之前你需要记住这些事情
关键字source
和.
(句点)是同一个命令。
如果FILENAME
不是文件的完整路径,该命令将在$PATH
环境变量中指定的目录中搜索文件。如果在$PATH
中找不到该文件,该命令将在当前目录中查找该文件。
如果给出任何ARGUMENTS
,它们将成为FILENAME
的位置参数。
如果FILENAME
存在,则源命令退出码为0
,否则,如果找不到文件,则返回1
。
在这些要点中,要关注的一点是second
,如果您使用的是#!/bin/bash
,则实际上需要为文件提供ABSOLUTE_PATH
,如果是,RELATIVE_PATH
只是不起作用你的情况然后我的朋友你只需要将路径更改为ABSOLUTE_FILE_PATH
。
【讨论】:
【参考方案5】:如果你定义了
#!/bin/bash
fun1()
echo "Fun1 from file1 $1"
fun1 Hello
. file2
fun1 Hello
exit 0
在文件 1 中(chmod 750 文件 1) 和文件2
fun1()
echo "Fun1 from file2 $1"
fun2()
echo "Fun1 from file1 $1"
然后运行 ./file2 你会得到 来自file1的Fun1 来自file2的Fun1 惊喜!!!您用 file2 中的 fun1 覆盖 file1 中的 fun1... 为了不这样做,您必须
declare -f pr_fun1=$fun1
. file2
unset -f fun1
fun1=$pr_fun1
unset -f pr_fun1
fun1 Hello
它会保存您之前对 fun1 的定义并使用之前的名称恢复它,删除不需要导入的名称。 每次从另一个文件导入函数时,您可能会记住两个方面:
-
你可以用相同的名字覆盖现有的(如果你想要的东西你必须如上所述保留它们)
导入导入文件的所有内容(函数和全局变量)
当心!这是一个危险的过程
【讨论】:
【参考方案6】:这是一个非常古老的帖子,我知道。但是我发现即使它位于同一目录中,我也无法获取另一个文件。
line 3: ./functions.bash: No such file or directory
然后我记得我已经为这种确切情况准备了一个方法,因为我是从一个 ini 文件导入的。所以这是我的解决方案,它允许我从任何地方(显然是源文件)运行程序,而无需对路径进行硬编码。
app="$(cd "$(dirname "$BASH_SOURCE[0]")" &>/dev/null && pwd)"
source $app/functions.bash
我不能把这归功于这个,已经有一段时间了,我不记得我从哪里得到的,否则我会相信他们,但这就是我用来源文件的全部。
【讨论】:
【参考方案7】:#vi function.sh
#!/bin/bash
f1()
echo "Hello $name"
f2()
echo "Enter your name: "
read name
f1
f2
#sh function.sh
这里的函数f2
会调用函数f1
【讨论】:
以上是关于我可以从另一个 shell 脚本调用一个 shell 脚本的函数吗?的主要内容,如果未能解决你的问题,请参考以下文章