111

我有 2 个 shell 脚本。

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

func1 
func2

first.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

我怎样才能实现它?

4

7 回答 7

171

像这样重构你的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
于 2012-05-30T19:47:42.443 回答
63

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

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

. /path/to/functions.sh

这将解释functions.sh为它的内容此时实际上存在于您的文件中。这是实现 shell 函数共享库的常用机制。

于 2012-05-30T19:21:42.467 回答
36

问题

当前接受的答案仅在重要条件下有效。鉴于...

/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将指定文件的内容加载到当前 shell
于 2017-02-07T22:22:47.203 回答
2

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您实际上需要为文件提供 a ,如果您遇到这种情况就行不通,那么我的朋友,您只需将路径更改为.ABSOLUTE_PATH#!/bin/bashRELATIVE_PATHABSOLUTE_FILE_PATH

于 2021-05-17T14:15:50.317 回答
0

这是一个非常古老的帖子,我知道。但是我发现即使它位于同一目录中,我也无法获取另一个文件。

line 3: ./functions.bash: No such file or directory

然后我记得我已经为这种确切情况准备了一个方法,因为我是从一个 ini 文件导入的。所以这是我的解决方案,它允许我从任何地方(显然是源文件)运行程序,而无需对路径进行硬编码。

app="$(cd "$(dirname "${BASH_SOURCE[0]}")" &>/dev/null && pwd)"
source $app/functions.bash

我不能对此表示赞赏,已经有一段时间了,我不记得我是从哪里得到的,否则我会相信他们,但这就是我用来源文件的全部。

于 2021-08-27T16:12:32.680 回答
0

如果你定义

    #!/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 的 Hello Fun1 你好惊喜!!!您用 file2 中的 fun1 覆盖 file1 中的 fun1... 为了不这样做,您必须

declare -f pr_fun1=$fun1
. file2
unset -f fun1
fun1=$pr_fun1
unset -f pr_fun1
fun1 Hello

它保存了您以前对 fun1 的定义,并使用以前的名称删除不需要导入的名称来恢复它。每次从另一个文件导入函数时,您可能会记住两个方面:

  1. 你可以用相同的名字覆盖现有的(如果你想要的东西,你必须如上所述保留它们)
  2. 导入导入文件的所有内容(函数和全局变量)小心!这是危险的程序
于 2017-08-19T18:37:51.770 回答
-6
#vi function.sh

#!/bin/bash
f1() {
    echo "Hello $name"
}

f2() {
    echo "Enter your name: "
    read name
    f1
}
f2

#sh function.sh

这里函数f2将调用函数f1

于 2013-09-11T16:00:20.250 回答