我可以从另一个Shell脚本调用Shell脚本的功能吗?


86

我有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`


}

第一.sh

second.sh cricket football

func1 love horror
func2 ball mystery

我该如何实现?



3
v=$(echo $1)是完全多余的。只是写fun2=$1。唯一的区别是$()(或反引号)将删除结尾的换行符。
威廉·珀塞尔

1
由于从shell脚本而不是从命令行调用函数没有什么特别的,因此这个问题可以简化为“如何调用bash函数?”。
汤姆·罗素

Answers:


145

second.sh像这样重构您的脚本:

function func1 {
   fun=$1
   book=$2
   printf "fun=%s,book=%s\n" "${fun}" "${book}"
}

function func2 {
   fun2=$1
   book2=$2
   printf "fun2=%s,book2=%s\n" "${fun2}" "${book2}"
}

然后从脚本中调用这些函数,first.sh如下所示:

source ./second.sh
func1 love horror
func2 ball mystery

输出:

fun=love,book=horror
fun2=ball,book2=mystery

12
为避免意外的副作用,请注意该source命令实际上将运行作为参数传递的脚本。
dvlcube

43

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

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

. /path/to/functions.sh

这将解释functions.sh为这时似乎文件中的内容实际上已经存在。这是用于实现Shell函数共享库的通用机制。


3
.是别名source吗?与接受的答案不同吗?
ajsharma

9
好吧,我首先回答,因此从技术上讲,可接受的答案与此相同:)。另外,虽然在许多shell中都是source别名.,但并非总是如此。例如,dashDebian上提供的软件包/bin/sh没有source命令。
larsk's

source命令在Ubuntu @ajsharma中不起作用。参考:在sh shell中找不到源命令
rajeshmag,

难道这个评论没有被最高评价吗?这是正确的#!/ bin / sh语法,其他语法仅在bash中有效。
xddq

20

问题

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

/foo/bar/first.sh

function func1 {  
   echo "Hello $1"
}

/foo/bar/second.sh

#!/bin/bash

source ./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相对于当前的工作路径,而不是脚本的路径。因此,一种解决方案可能是利用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中

0

如果您定义

    #!/bin/bash
        fun1(){
          echo "Fun1 from file1 $1"
        }
fun1 Hello
. file2 
fun1 Hello
exit 0

在file1(chmod 750 file1)和file2中

   fun1(){
      echo "Fun1 from file2 $1"
    }
    fun2(){
      echo "Fun1 from file1 $1"
    }

并运行./file2,您将从file1获得Fun1。Hello Fun1从file2获得Hello Surprise!您用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. 导入导入文件的所有内容(也包括函数和全局变量)注意!这是危险的程序

-5
#vi function.sh

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

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

#sh function.sh

这里的函数f2会调用函数f1

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.