我可以从另一个 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/shdash 软件包没有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 是相对于当前工作路径的,而不是脚本的路径。因此,一种解决方案可能是利用 subshel​​l 并运行

(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 脚本的函数吗?的主要内容,如果未能解决你的问题,请参考以下文章

从另一个shell脚本调用函数[重复]

使用相对路径从另一个脚本调用一个 shell 脚本

Shel脚本-初步入门之《02 什么是 Shell 脚本》

shell编程规范与变量

学习Shell脚本

从另一个环境调用 Perl 在后台