別のシェルスクリプトからシェルスクリプトの関数を呼び出すことはできますか?


87

2つのシェルスクリプトがあります。

2番目のシェルスクリプトには、次の関数second.shが含まれています

func1 
func2

first.shは、いくつかのパラメーターを使用して2番目のシェルスクリプトを呼び出し、その関数に固有の他のいくつかのパラメーターを使用して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

どうすればそれを達成できますか?



3
v=$(echo $1)完全に冗長です。書くだけfun2=$1です。唯一の違いは、$()(またはバックティック)が末尾の改行を削除することです。
William Pursell 2012年

1
コマンドラインとは対照的に、シェルスクリプトから関数を呼び出すことについて特別なことは何もないので、この質問は「bash関数を呼び出す方法」に減らすことができます。
トムラッセル

回答:


146

次の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 2017年

44

別のシェルスクリプトで関数を直接呼び出すことはできません。

関数定義を別のファイルに移動してから、.次のようにコマンドを使用してスクリプトにロードできます。

. /path/to/functions.sh

これはfunctions.sh、そのコンテンツがこの時点で実際にファイルに存在していたかのように解釈されます。これは、シェル関数の共有ライブラリを実装するための一般的なメカニズムです。


3
.エイリアスなので、これは受け入れられた答えと同じではありませんsourceか?
ajsharma

10
さて、私は最初に答えたので、技術的に受け入れられた答えはこれと同じです:)。また、source.多くのシェルのエイリアスですが、常にそうであるとは限りません。たとえばdash、を提供するDebianのパッケージに/bin/shは、sourceコマンドがありません。
larsks 2018

sourceコマンドはUbuntu @ ajsharmaでは機能しませんでした。参考:sourceコマンドはshシェルでは見られない
rajeshmag

このコメントが最高に賛成されないほど奇妙ですか?これは正しい#!/ bin / sh構文であり、もう1つはbashでのみ機能します。
xddq

21

問題

現在受け入れられている回答は、重要な条件下でのみ機能します。与えられた...

/foo/bar/first.sh

function func1 {  
   echo "Hello $1"
}

そして

/foo/bar/second.sh

#!/bin/bash

source ./first.sh
func1 World

これfirst.shは、が配置されているのと同じディレクトリ内からが実行された場合にのみ機能しfirst.shます。つまり、シェルの現在の作業パスが、の場合、/fooコマンドを実行しようとします

cd /foo
./bar/second.sh

エラーを出力します:

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

これsource ./first.shは、がスクリプトのパスではなく、現在の作業パスに関連しているためです。したがって、1つの解決策は、サブシェルを利用して実行することです。

(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インポートされたシェルスクリプトの名前を追加するだけです
  • source 指定されたファイルのコンテンツを現在のシェルにロードします

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が取得されます。file2からFun1が取得されます。HelloSurprise!!! file1のfun1をfile2のfun1で上書きします...そうしないようにするには、

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

fun1の以前の定義を保存し、インポートされた不要な名前を削除して以前の名前で復元します。別のファイルから関数をインポートするたびに、次の2つの側面を覚えているかもしれません。

  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

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.