Bagaimana cara menjalankan fungsi dari skrip di baris perintah?

119

Saya memiliki skrip yang memiliki beberapa fungsi.

Bisakah saya menjalankan salah satu fungsi langsung dari baris perintah?

Sesuatu seperti ini?

myScript.sh func()
AAaa
sumber

Jawaban:

66

Jika skrip hanya mendefinisikan fungsi dan tidak melakukan yang lain, Anda dapat mengeksekusi skrip terlebih dahulu dalam konteks shell saat ini menggunakan perintah sourceor .dan kemudian cukup memanggil fungsinya. Lihat help sourceuntuk informasi lebih lanjut.

Sven Marnach
sumber
1
Satu-satunya masalah dengan metode ini adalah jika Anda menggunakan exitdalam fungsi Anda, itu akan menutup terminal setelah fungsi dijalankan. Apakah ada cara lain untuk menyiasatinya? @SvenMarnach
pengguna1527227
@ user1527227: Lanjutkan dengan jawaban berikutnya dalam kasus itu, asalkan Anda memiliki kendali atas skrip shell. Jika tidak, Anda dapat memanggil subkulit interaktif terlebih dahulu (cukup masuk bash), dan exithanya akan mengakhiri subkulit, tetapi tidak terminal Anda.
Sven Marnach
238

Nah, sementara jawaban lain benar - Anda pasti dapat melakukan sesuatu yang lain: jika Anda memiliki akses ke skrip bash, Anda dapat memodifikasinya, dan cukup letakkan di bagian akhir parameter khusus "$@"- yang akan diperluas ke argumen baris perintah Anda tentukan, dan karena "sendiri" shell akan mencoba memanggilnya kata demi kata; dan di sini Anda bisa menentukan nama fungsi sebagai argumen pertama. Contoh:

$ 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

Untuk memoles, Anda dapat memverifikasi terlebih dahulu bahwa perintah tersebut ada dan merupakan fungsi:

# 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
sdaau
sumber
16
Gunakan "$@"dalam banyak kasus. $@tidak aman dalam beberapa kasus.
fumiyas
1
Bagaimana cara menjalankan lebih dari satu fungsi? misalnya bisakah saya lari bash test.sh testA testB?
Jeff Pang
Ini juga perlu dibungkus dengan [ ! -z "$1" ]jika tidak sumber akan memunculkan pernyataan lain dalam beberapa
versi
Saya telah mencari dari dekat dan jauh untuk variabel ajaib "$ @" ini untuk menggunakan fungsi apa pun yang dipanggil pada file, terima kasih @sdaau!
Justin Hammond
36

Perintah berikut pertama-tama mendaftarkan fungsi dalam konteks, lalu memanggilnya:

. ./myScript.sh && function_name
TimonWang
sumber
1
Anda juga dapat menggunakan sumber. Seperti di - sumber myScript.sh && function_name
stolen_leaves
17

Singkatnya, tidak.

Anda dapat mengimpor semua fungsi dalam skrip ke lingkungan Anda dengan source(help source untuk detailnya), yang kemudian memungkinkan Anda untuk memanggilnya. Ini juga memiliki efek menjalankan skrip, jadi berhati-hatilah.

Tidak ada cara untuk memanggil fungsi dari skrip shell seolah-olah itu adalah pustaka bersama.

sorpigal
sumber
1
Saya pikir ini harus diberi bobot lebih sebagai jawaban yang tepat. Saya mencoba melakukan sesuatu yang mirip dengan apa yang diinginkan OP, tetapi skrip shell tidak direkayasa untuk "pengembangan OOP yang rapi" (IMHO).
Dan L
4

Menggunakan 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

Skrip ini akan menjalankan fungsi fun1 dan fun2 tetapi jika Anda memulainya dengan opsi fun1 atau fun2 itu hanya akan menjalankan fungsi yang diberikan dengan args (jika tersedia) dan keluar. Pemakaian

$ ./test 
run function1
run function2

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

Sunting: PERINGATAN - tampaknya ini tidak berfungsi di semua kasus, tetapi berfungsi dengan baik pada banyak skrip publik.

Jika Anda memiliki skrip bash yang disebut "control" dan di dalamnya Anda memiliki fungsi yang disebut "build":

function build() { 
  ... 
}

Kemudian Anda dapat menyebutnya seperti ini (dari direktori tempatnya):

./control build

Jika ada di dalam folder lain, itu akan membuatnya:

another_folder/control build

Jika file Anda bernama "control.sh", itu akan membuat fungsi tersebut dapat dipanggil seperti ini:

./control.sh build
Arturas M
sumber
1
Ini tidak berfungsi di shell interaktif untuk saya. Tapi ini berhasil:. ./control.sh && build
saulius2
1

Saya memiliki situasi di mana saya memerlukan fungsi dari skrip bash yang tidak boleh dijalankan sebelumnya (misalnya oleh source) dan masalahnya @$adalah myScript.sh kemudian dijalankan dua kali, tampaknya ... Jadi saya telah mendapatkan ide untuk mengeluarkan fungsinya dengan sed:

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

Dan untuk mengeksekusinya pada saat saya membutuhkannya, saya memasukkannya ke dalam file dan menggunakan source:

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

vchrizz
sumber
0

Anda dapat memanggil fungsi dari argumen baris perintah seperti di bawah ini

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

Setelah fungsi selesai, masukkan $ 1 untuk menerima argumen, misalkan kode di atas disimpan di fun.sh untuk menjalankan fungsi ./fun.sh irfan & ./fun.sh config

Irfan Khan
sumber
0

Pos terpecahkan tetapi saya ingin menyebutkan solusi pilihan saya. Yakni, tentukan skrip satu baris generik eval_func.sh:

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

Kemudian panggil fungsi apa pun dalam skrip apa pun melalui:

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

Masalah yang saya hadapi dengan solusi yang diterima adalah ketika mencari skrip berisi fungsi saya dalam skrip lain, argumen yang terakhir akan dievaluasi oleh yang pertama, menyebabkan kesalahan.

Evan
sumber