コマンドラインでスクリプトから関数を実行するにはどうすればよいですか?


119

いくつかの機能を持つスクリプトがあります。

関数の1つをコマンドラインから直接実行できますか?

このようなもの?

myScript.sh func()

回答:


66

スクリプトが関数のみを定義し、他に何もしない場合は、最初にsourceor .コマンドを使用して現在のシェルのコンテキスト内でスクリプトを実行し、次に関数を呼び出すだけです。詳細についてはhelp source、を参照してください。


1
このメソッドの唯一の問題exitは、関数で使用すると、関数の実行後にターミナルが閉じることです。これを回避する方法はありますか?@SvenMarnach
user1527227

@ user1527227:シェルスクリプトを制御できる場合、その場合は次の回答に進んでください。そうしない場合は、最初に対話型サブシェルを呼び出すことができ(と入力するだけbash)、exitターミナルではなくサブシェルだけを終了します。
Sven Marnach 14

238

まあ、他の答えは正しいですが、確かに何か他のことができます。bashスクリプトにアクセスできる場合は、スクリプトを変更して、特別なパラメーターの最後に配置するだけ"$@"で、コマンドラインの引数に展開できます。指定すると、「単独」であるため、シェルはそれらを逐語的に呼び出そうとします。ここでは、最初の引数として関数名を指定できます。例:

$ cat test.sh
testA() {
  echo "TEST A $1";
}

testB() {
  echo "TEST B $2";
}

"$@"


$ bash test.sh
$ bash test.sh testA
TEST A 
$ bash test.sh testA arg1 arg2
TEST A arg1
$ bash test.sh testB arg1 arg2
TEST B arg2

磨く場合、最初にコマンドが存在し、関数であることを確認できます。

# Check if the function exists (bash specific)
if declare -f "$1" > /dev/null
then
  # call arguments verbatim
  "$@"
else
  # Show a helpful error
  echo "'$1' is not a known function name" >&2
  exit 1
fi

16
"$@"ほとんどの場合に使用します。$@場合によっては安全ではありません。
フミヤ

1
関数以上のものを実行するには?たとえば、実行できますbash test.sh testA testBか?
ジェフ・パン

これはまた、[ ! -z "$1" ]そうでなければソースでラップする必要があります。いくつかのbashバージョンでelseステートメントが発生します
JackLeo

私はこの魔法の「$ @」変数を探して、ファイルで呼び出された関数を使用できるようにしてきました。@ sdaauに感謝します。
ジャスティンハモンド

36

次のコマンドは、最初に関数をコンテキストに登録し、次にそれを呼び出します。

. ./myScript.sh && function_name

1
単純にソースを使用することもできます。のように-ソースmyScript.sh && function_name
stolen_leaves

17

簡単に言えば、いいえ。

sourcehelp source詳細については)を使用して、スクリプト内のすべての関数を環境にインポートできます。これにより、関数を呼び出すことができます。これはスクリプトを実行する効果もあるので、注意してください。

共有ライブラリであるかのように、シェルスクリプトから関数を呼び出す方法はありません。


1
これは適切な答えとしてより重要視されるべきだと思います。私はOPが望んでいるものと同様のことを試みましたが、シェルスクリプトは単に "クリーンカット、OOP開発"(IMHO)用に設計されていません。
Dan L

4

使用する case

#!/bin/bash

fun1 () {
    echo "run function1"
    [[ "$@" ]] && echo "options: $@"
}

fun2 () {
    echo "run function2"
    [[ "$@" ]] && echo "options: $@"
}

case $1 in
    fun1) "$@"; exit;;
    fun2) "$@"; exit;;
esac

fun1
fun2

このスクリプトは関数fun1とfun2を実行しますが、オプションfun1またはfun2で開始すると、args(指定されている場合)で指定された関数のみが実行され、終了します。使用法

$ ./test 
run function1
run function2

$ ./test fun2 a b c
run function2
options: a b c

1

編集:警告-これはすべてのケースで機能するわけではないようですが、多くの公開スクリプトでうまく機能します。

「control」というbashスクリプトがあり、その中に「build」という関数がある場合:

function build() { 
  ... 
}

次に、(それが存在するディレクトリから)次のように呼び出すことができます:

./control build

別のフォルダ内にある場合は、次のようになります。

another_folder/control build

ファイルが「control.sh」と呼ばれている場合、それに応じて関数は次のように呼び出し可能になります。

./control.sh build

1
これは、インタラクティブシェルでは機能しませんでした。しかし、これは. ./control.sh && build
うまくいき

1

以前に(たとえばによってsource)実行してはならないbashスクリプトからの関数が必要な状況があり、@$myScript.shが2回実行されるという問題があるようです...だから私はアイデアを思いつきました関数をsedで取得するには:

sed -n "/^func ()/,/^}/p" myScript.sh

そして、必要なときに実行するには、ファイルに入れて使用しますsource

sed -n "/^func ()/,/^}/p" myScript.sh > func.sh; source func.sh; rm func.sh


0

以下のようにコマンドライン引数から関数を呼び出すことができます

function irfan() {
echo "Irfan khan"
date
hostname
}
function config() {
ifconfig
echo "hey"
}
$1

関数が終了したら$ 1を入力して引数を受け入れ、上記のコードをfun.shに保存して関数を実行します./fun.sh irfan&./fun.sh config


0

ポストを解決しましたが、私は私の好ましい解決策に言及したいと思います。つまり、一般的な1行のスクリプトを定義しますeval_func.sh

#!/bin/bash
source $1 && shift && "@a"

次に、以下を介してスクリプト内の関数を呼び出します。

./eval_func.sh <any script> <any function> <any args>...

受け入れられた解決策で遭遇した問題は、別のスクリプト内で関数を含むスクリプトを調達すると、後者の引数が前者によって評価され、エラーが発生することです。

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