简体   繁体   English

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

[英]Can I call a function of a shell script from another shell script?

I have 2 shell scripts.我有 2 个 shell 脚本。

The second shell script contains following functions second.sh第二个 shell 脚本包含以下函数second.sh

func1 
func2

The first.sh will call the second shell script with some parameters and will call func1 and func2 with some other parameters specific to that function. first.sh 将使用一些参数调用第二个 shell 脚本,并使用特定于该函数的一些其他参数调用 func1 和 func2。

Here is the example of what I am talking about这是我正在谈论的示例

second.sh第二个.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第一个.sh

second.sh cricket football

func1 love horror
func2 ball mystery

How can I achieve it?我怎样才能实现它?

Refactor your second.sh script like this:像这样重构你的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"
}

And then call these functions from script first.sh like this:然后像这样从 script first.sh调用这些函数:

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

OUTPUT:输出:

func=love,book=horror
func2=ball,book2=mystery

You can't directly call a function in another shell script.您不能直接调用另一个 shell 脚本中的函数。

You can move your function definitions into a separate file and then load them into your script using the .您可以将函数定义移动到单独的文件中,然后使用. command, like this:命令,像这样:

. /path/to/functions.sh

This will interpret functions.sh as if it's content were actually present in your file at this point.这将解释functions.sh就好像它的内容此时实际存在于您的文件中一样。 This is a common mechanism for implementing shared libraries of shell functions.这是实现shell函数共享库的常用机制。

The problem问题

The currenly accepted answer works only under important condition.当前接受的答案仅在重要条件下才有效。 Given...鉴于...

/foo/bar/first.sh : /foo/bar/first.sh

function func1 {  
   echo "Hello $1"
}

and

/foo/bar/second.sh : /foo/bar/second.sh

#!/bin/bash

source ./first.sh
func1 World

this works only if the first.sh is executed from within the same directory where the first.sh is located.只有在first.sh所在的同一目录中执行first.sh Ie. IE。 if the current working path of shell is /foo , the attempt to run command如果 shell 的当前工作路径是/foo ,则尝试运行命令

cd /foo
./bar/second.sh

prints error:打印错误:

/foo/bar/second.sh: line 4: func1: command not found

That's because the source ./first.sh is relative to current working path, not the path of the script.这是因为source ./first.sh是相对于当前工作路径的,而不是脚本的路径。 Hence one solution might be to utilize subshell and run因此,一种解决方案可能是利用 subshel​​l 并运行

(cd /foo/bar; ./second.sh)

More generic solution更通用的解决方案

Given...鉴于...

/foo/bar/first.sh : /foo/bar/first.sh

function func1 {  
   echo "Hello $1"
}

and

/foo/bar/second.sh : /foo/bar/second.sh

#!/bin/bash

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

func1 World

then然后

cd /foo
./bar/second.sh

prints印刷

Hello World

How it works这个怎么运作

  • $0 returns relative or absolute path to the executed script $0返回已执行脚本的相对或绝对路径
  • dirname returns relative path to directory, where the $0 script exists dirname返回目录的相对路径,其中存在 $0 脚本
  • $( dirname "$0" ) the dirname "$0" command returns relative path to directory of executed script, which is then used as argument for source command $( dirname "$0" ) dirname "$0"命令返回执行脚本目录的相对路径,然后用作source命令的参数
  • in "second.sh", /first.sh just appends the name of imported shell script在“second.sh”中,/ /first.sh只是附加了导入的 shell 脚本的名称
  • source loads content of specified file into current shell source将指定文件的内容加载到当前 shell 中

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

You need to keep these things in your mind before using it使用前你需要牢记这些事情

  • Keyword source and .关键字source. (a period) are the same command. (句号)是相同的命令。
  • If the FILENAME is not a full path to a file, the command will search for the file in the directories specified in the $PATH environmental variable .如果FILENAME不是文件的完整路径,该命令将在$PATH环境变量中指定的目录中搜索文件。 If the file is not found in the $PATH , the command will look for the file in the current directory.如果在$PATH找不到该文件,该命令将在当前目录中查找该文件。
  • If any ARGUMENTS are given, they will become positional parameters to the FILENAME .如果给出了任何ARGUMENTS ,它们将成为FILENAME位置参数。
  • If the FILENAME exists, the source command exit code is 0 , otherwise, if the file is not found it will return 1 .如果FILENAME存在,则源命令退出代码为0 ,否则,如果找不到文件,则返回1

Among these points the point to be focused on is the second one, you actually need to provide a ABSOLUTE_PATH to the file if you are using #!/bin/bash , RELATIVE_PATH just doesn't work if that is the case with you then my friend you just need to change the path to ABSOLUTE_FILE_PATH .在这些点中,要关注的点是second点,如果您使用的是#!/bin/bash ,您实际上需要为文件提供ABSOLUTE_PATH ,如果您是这种情况,则RELATIVE_PATH不起作用,那么我的朋友,您只需要将路径更改为ABSOLUTE_FILE_PATH

If you define如果你定义

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

in file1(chmod 750 file1) and file2在文件 1(chmod 750 文件 1)和文件 2 中

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

and run ./file2 you'll get Fun1 from file1 Hello Fun1 from file2 Hello Surprise!!!并运行 ./file2 你会得到 Fun1 from file1 Hello Fun1 from file2 Hello Surprise!!! You overwrite fun1 in file1 with fun1 from file2... So as not to do so you must你用文件 2 中的 fun1 覆盖文件 1 中的 fun1 ......为了不这样做,你必须

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

it's save your previous definition for fun1 and restore it with the previous name deleting not needed imported one.它保存了您以前对 fun1 的定义,并使用以前的名称恢复它,删除不需要的导入名称。 Every time you import functions from another file you may remember two aspects:每次从另一个文件导入函数时,您可能会记住两个方面:

  1. you may overwrite existing ones with the same names(if that the thing you want you must preserve them as described above)您可以使用相同的名称覆盖现有的(如果是您想要的东西,则必须如上所述保留它们)
  2. import all content of import file(functions and global variables too) Be careful!导入导入文件的所有内容(函数和全局变量) 注意! It's dangerous procedure这是危险的程序

This is a very old post, I am aware.这是一个很老的帖子,我知道。 However I found I could not source another file even though it was in the same directory.但是我发现即使它在同一目录中,我也无法获取另一个文件。

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

Then I remembered I already have in place a method for this exact situation because I import from an ini file.然后我想起我已经为这种确切情况制定了一种方法,因为我是从 ini 文件导入的。 So here is my solution that allows me to run a program from anywhere (and apparently source files) without hardcoding the paths.所以这是我的解决方案,它允许我从任何地方(显然是源文件)运行程序,而无需对路径进行硬编码。

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

I cannot take credit for this, its been a while and I can't recall where I got the line from otherwise I would credit them, but that's all I use to source files.我不能相信这一点,已经有一段时间了,我不记得我从哪里得到了这条线,否则我会相信他们,但这就是我用来处理源文件的全部内容。

#vi function.sh

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

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

#sh function.sh

Here function f2 will call function f1这里函数f2将调用函数f1

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM