我可以从另一个shell脚本调用shell脚本的函数吗?

我可以从另一个shell脚本调用shell脚本的函数吗?,shell,unix,Shell,Unix,我有两个shell脚本 第二个shell脚本包含以下函数 第二,sh sh将使用一些参数和参数调用第二个shell脚本 将使用特定于该函数的其他一些参数调用func1和func2 这就是我所说的例子 第二,sh val1=`echo $1` val2=`echo $2` function func1 { fun=`echo $1` book=`echo $2` } function func2 { fun2=`echo $1` book2=`echo $2` } 第一,sh se

我有两个shell脚本

第二个shell脚本包含以下函数 第二,sh

sh将使用一些参数和参数调用第二个shell脚本 将使用特定于该函数的其他一些参数调用func1和func2

这就是我所说的例子

第二,sh

val1=`echo $1`
val2=`echo $2`

function func1 {

fun=`echo $1`
book=`echo $2`

}

function func2 {

fun2=`echo $1`
book2=`echo $2`


}
第一,sh

second.sh cricket football

func1 love horror
func2 ball mystery

如何实现它?

您不能直接在另一个shell脚本中调用函数

您可以将函数定义移动到单独的文件中,然后使用
命令将其加载到脚本中,如下所示:

. /path/to/functions.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"
}
source ./second.sh
func1 love horror
func2 ball mystery

这将解释
functions.sh
,就好像此时文件中实际存在它的内容一样。这是实现shell函数共享库的常用机制。

重构
second.sh
脚本,如下所示:

. /path/to/functions.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"
}
source ./second.sh
func1 love horror
func2 ball mystery
然后首先从script
调用这些函数。sh
如下:

. /path/to/functions.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"
}
source ./second.sh
func1 love horror
func2 ball mystery
输出:

func=love,book=horror
func2=ball,book2=mystery
function func1 {  
   echo "Hello $1"
}
#!/bin/bash

source ./first.sh
func1 World
function func1 {  
   echo "Hello $1"
}
#!/bin/bash

source $(dirname "$0")/first.sh

func1 World
这里函数
f2
将调用函数
f1

解决问题 目前公认的答案只有在重要条件下才有效。鉴于

/foo/bar/first.sh

func=love,book=horror
func2=ball,book2=mystery
function func1 {  
   echo "Hello $1"
}
#!/bin/bash

source ./first.sh
func1 World
function func1 {  
   echo "Hello $1"
}
#!/bin/bash

source $(dirname "$0")/first.sh

func1 World

/foo/bar/second.sh

func=love,book=horror
func2=ball,book2=mystery
function func1 {  
   echo "Hello $1"
}
#!/bin/bash

source ./first.sh
func1 World
function func1 {  
   echo "Hello $1"
}
#!/bin/bash

source $(dirname "$0")/first.sh

func1 World
仅当从
first.sh
所在的同一目录中执行
first.sh
时,此操作才有效。即,如果shell的当前工作路径为
/foo
,则尝试运行命令

cd /foo
./bar/second.sh
打印错误:

/foo/bar/second.sh: line 4: func1: command not found
这是因为
source./first.sh
是相对于当前工作路径的,而不是脚本的路径。因此,一种解决方案可能是利用子shell并运行

(cd /foo/bar; ./second.sh)
更通用的解决方案 鉴于

/foo/bar/first.sh

func=love,book=horror
func2=ball,book2=mystery
function func1 {  
   echo "Hello $1"
}
#!/bin/bash

source ./first.sh
func1 World
function func1 {  
   echo "Hello $1"
}
#!/bin/bash

source $(dirname "$0")/first.sh

func1 World

/foo/bar/second.sh

func=love,book=horror
func2=ball,book2=mystery
function func1 {  
   echo "Hello $1"
}
#!/bin/bash

source ./first.sh
func1 World
function func1 {  
   echo "Hello $1"
}
#!/bin/bash

source $(dirname "$0")/first.sh

func1 World
然后

印刷品

Hello World
工作原理
  • $0
    返回已执行脚本的相对或绝对路径
  • dirname
    返回$0脚本所在目录的相对路径
  • $(dirname“$0”)
    命令返回相对 执行脚本的目录路径,然后用作
    source
    命令的参数
  • 在“second.sh”中,
    /first.sh
    只是附加导入的shell脚本的名称
  • source
    将指定文件的内容加载到当前 壳
如果您定义

    #!/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您将获得 Fun1来自file1你好 Fun1来自file2你好 惊喜您使用文件2中的fun1覆盖文件1中的fun1。。。为了不这样做,你必须

declare -f pr_fun1=$fun1
. file2
unset -f fun1
fun1=$pr_fun1
unset -f pr_fun1
fun1 Hello
将以前的定义保存为fun1,并使用以前的名称将其恢复为删除不需要的导入定义。 每次从另一个文件导入函数时,您可能会记住两个方面:

  • 您可以用相同的名称覆盖现有的名称(如果需要,则必须如上所述保留它们)
  • 导入导入文件的所有内容(也包括函数和全局变量) 小心!这是一个危险的程序
  • second.sh

    #/bin/bash
    函数func1(){
    fun=“$1”
    book=“$2”
    echo“$fun$book\n”
    }
    函数func2(){
    fun2=“$1”
    book2=“$2”
    printf“$fun2,$book2\n”
    }
    
    first.sh

    #/bin/bash
    source/absolute\u path\u to/second.sh
    爱情恐怖
    足球之谜
    
    在使用之前,你需要记住这些东西
    • 关键字
      source
      (一个句点)是同一个命令
    • 如果
      FILENAME
      不是文件的完整路径,则该命令将在
      $path
      环境变量中指定的目录中搜索该文件。如果在
      $PATH
      中找不到该文件,该命令将在当前目录中查找该文件
    • 如果给出任何
      参数
      ,它们将成为
      文件名
      的位置参数
    • 如果
      文件名
      存在,则源命令退出代码为
      0
      ,否则,如果未找到该文件,将返回
      1

    在这些点中,需要重点关注的点是第二点,如果您使用的是
    ,实际上需要为文件提供一个
    绝对路径
    /bin/bash
    RELATIVE\u PATH
    就是不起作用,如果你是这样的话,那么我的朋友,你只需要将路径更改为
    绝对文件\u PATH

    复制-
    v=$(echo$1)
    是完全多余的。只需写
    fun2=$1
    。唯一的区别是,
    $()
    (或backticks)将删除尾随的换行符。由于从shell脚本调用函数与从命令行调用函数没有什么不同,因此可以将此问题简化为“如何调用bash函数?”以避免意外的副作用,请注意,
    source
    命令实际上会运行作为参数传递的脚本。@dvlcube如果您能建议一个替代方法,那就更好了。这个答案很清楚,也很好。重要的是,它描述了一些人可能遇到的问题,并提供了一个优雅的通用解决方案。@Alpha2k我不确定是否有替代方案。这句话的意思是“小心你把什么放进你的源文件中”这与公认的答案不一样吗,因为
    源代码的别名?好吧,我是先回答的,所以从技术上讲,公认的答案与此相同:)。另外,虽然在许多shell中,
    source
    的别名,但情况并非总是如此。例如,Debian上提供
    /bin/sh
    dash
    包没有
    source
    命令。参考:太奇怪了,这条评论没有被提升为