Cara mendefinisikan fungsi Bash yang dapat digunakan oleh skrip yang berbeda

13

Saya telah mendefinisikan bashfungsi dalam ~/.bashrcfile saya . Ini memungkinkan saya untuk menggunakannya di terminal shell. Namun, sepertinya tidak ada ketika saya menyebutnya dari dalam skrip.

Bagaimana saya bisa mendefinisikan bashfungsi yang akan digunakan oleh skrip juga?

Onturenio
sumber
Tapi .bash_profile saya pada dasarnya membaca file .basrc, jadi saya akan mengharapkan hasilnya tetap sama terlepas saya menggunakan shell login atau non-login.
Onturenio
Apakah Anda menggunakan /bin/shjalur shebang?
Kevin

Jawaban:

9

~/.bash_profiledan ~/.bashrctidak dibaca oleh skrip, dan fungsi tidak diekspor secara default. Untuk melakukannya, Anda dapat menggunakan export -fseperti:

$ cat > script << 'EOF'
#!/bin/bash
foo
EOF
$ chmod a+x script
$ ./script
./script: line 2: foo: command not found
$ foo() { echo "works" ; } 
$ export -f foo
$ ./script
works

export -f foojuga bisa dipanggil ~/.bash_profileuntuk membuat fungsi ini tersedia untuk skrip setelah masuk. Berhati-hatilah karena export -ftidak portabel.

Solusi yang lebih baik adalah dengan sumber file yang berisi fungsi menggunakan . file. Ini jauh lebih portabel, dan tidak bergantung pada lingkungan Anda diatur dengan cara tertentu.

Chris Down
sumber
mengapa tidak mendeklarasikan fungsi seperti function myFunction { ... }di ~/.bash_profiledan Anda baik untuk pergi?
amfibi
Jika saya mengerti dengan benar jawaban Anda (mengenai sumber file dengan fungsi), ini berarti bahwa saya harus sumber file secara eksplisit di setiap skrip, yang cukup menjengkelkan. Ini tidak jauh lebih rumit dari sekadar menyalin-menempelkan fungsi itu sendiri di setiap skrip. Saya akan menyimpan beberapa baris, tentu saja, tapi hanya itu. Namun, exportsolusinya tampaknya berfungsi dengan baik. Terima kasih.
Onturenio
@foampile, inilah tepatnya yang saya lakukan dan tidak berfungsi saat memanggil fungsi dari skrip.
Onturenio
1
@Onturenio: metode kedua @ chris-down yang diajukan memang lebih baik: 1) Ketika seseorang membaca skrip, mereka sadar bahwa itu memerlukan beberapa foofungsi dari beberapa file2) Anda dapat lebih mengontrol konten itu filedaripada memastikan bahwa shell yang memanggil tidak berubah foosebelum menjalankan skrip Anda. Anda dapat menambahkan pemeriksaan keamanan fileuntuk memastikan itu tidak rusak, misalnya. (tidak mudah, tetapi mungkin). (yah, Anda juga bisa melakukan pemeriksaan pada fungsi foo yang ditentukan ... tetapi Anda mengerti filemaksud saya ^^ Saya pikir metode 2 lebih bersih.) 3) hanya akan berisi apa yang dibutuhkan, bukan lebih.
Olivier Dulac
8

.bashrchanya dibaca oleh cangkang interaktif. (Sebenarnya, itu penyederhanaan berlebihan: bash unik dalam hal ini. Bash tidak membaca .bashrcapakah itu shell login, interaktif atau tidak. Dan ada pengecualian bahkan untuk pengecualian: jika proses induk bash adalah rshdatau sshd, maka bash membaca .bashrc, apakah itu interaktif atau tidak.)

Letakkan definisi fungsi Anda dalam file di tempat yang diketahui, dan gunakan builtin .(juga dieja source) untuk memasukkan file itu dalam skrip.

$ cat ~/lib/bash/my_functions.bash
foo () {

$ cat ~/bin/myscript
#!/bin/bash
. ~/lib/bash/my_functions.bash
foo bar

Jika mau, Anda dapat mengikuti fitur pengisian otomatis ksh. Masukkan setiap definisi fungsi dalam file dengan nama yang sama dengan fungsi. Daftar direktori yang berisi definisi fungsi dalam FPATHvariabel (daftar direktori yang dipisahkan oleh titik dua). Berikut ini perkiraan kasar dari ksh autoloadyang sebenarnya memuat fungsi segera alih-alih sesuai permintaan:

autoload () {
  set -- "$(set +f; IFS=:;
            for d in $FPATH; do
              if [ -r "$d/$1" ]; then echo -E "$d/$1"; break; fi;
            done)"
  [[ -n $1 ]] && . "$1"
}
Gilles 'SANGAT berhenti menjadi jahat'
sumber
+1 untuk autoload, meskipun saya sarankan menggunakan yang bash. Yang terbaru mendukung muatan malas.
Bintang laut
0

Apakah Anda memerlukan fungsi? Jika tidak, pertimbangkan untuk mencabut logika menjadi skrip Bash yang terpisah dan berdiri sendiri di blog Anda $PATH. Misalnya, saya punya ini di ~/.bashrc:

# echo public IP address
alias wanip='dig +short myip.opendns.com @resolver1.opendns.com'

~/binada di saya $PATH, jadi saya buat ~/bin/wanipdengan konten berikut:

#!/bin/bash

# echo public IP address
dig +short myip.opendns.com @resolver1.opendns.com

Dan berlari chmod 0755 ~/bin/wanipuntuk membuatnya bisa dieksekusi. Sekarang saya dapat mengeksekusi wanipdari skrip lain.

Saya suka memiliki wanipskrip Bash yang berdiri sendiri. Ini mengingatkan saya bahwa saya ingin logika ini tersedia secara umum (selain hanya dalam sesi Bash interaktif saya saat ini). Script dengan baik merangkum logika dan dokumentasi yang sama.

Adam Monsen
sumber