Saat ini saya sedang melakukan beberapa unit test yang dijalankan dari bash. Tes unit diinisialisasi, dieksekusi dan dibersihkan dalam skrip bash. Script ini biasanya berisi fungsi init (), execute () dan cleanup (). Tetapi mereka tidak wajib. Saya ingin menguji apakah mereka didefinisikan atau tidak.
Saya melakukan ini sebelumnya dengan menangkap dan membius sumbernya, tetapi tampaknya salah. Apakah ada cara yang lebih elegan untuk melakukan ini?
Sunting: Sniplet berikut ini berfungsi seperti pesona:
fn_exists()
{
LC_ALL=C type $1 | grep -q 'shell function'
}
fn_exists foo || foo() { :; }
type -t
dan==
.type test_function
mengatakantest_function on funktio.
saat menggunakan bahasa Finlandia danist eine Funktion
saat menggunakan bahasa Jerman.LC_ALL=C
keJawaban:
Saya pikir Anda sedang mencari perintah 'ketik'. Ini akan memberi tahu Anda apakah ada fungsi, fungsi bawaan, perintah eksternal, atau tidak didefinisikan. Contoh:
sumber
type -t $function
adalah tiket makan.type [-t]
memang bagus untuk memberi tahu Anda apa masalahnya, tetapi ketika menguji apakah ada fungsi, itu lambat karena Anda harus menggunakan pipa untuk menangkap atau menggunakan backtick, yang keduanya menghasilkan subproses.type -t realpath > /dev/shm/tmpfile ; read < /dev/shm/tmpfile
(contoh buruk). Namun, menyatakan adalah jawaban terbaik karena memiliki 0 disk io.sumber
type -t
, Anda dapat mengandalkan status keluar sebagai gantinya. Saya sudah lama terbiasatype program_name > /dev/null 2>&1 && program_name arguments || echo "error"
melihat apakah saya bisa memanggil sesuatu. Jelas metodetype -t
dan di atas juga memungkinkan untuk mendeteksi tipe, bukan hanya apakah itu "bisa dipanggil".Jika menyatakan 10x lebih cepat dari tes, ini tampaknya jawaban yang jelas.
Sunting: Di bawah,
-f
opsi ini berlebihan dengan BASH, jangan ragu untuk meninggalkannya. Secara pribadi, saya mengalami kesulitan mengingat opsi mana yang melakukan itu, jadi saya hanya menggunakan keduanya. -f menunjukkan fungsi, dan -F menunjukkan nama fungsi.Opsi "-F" untuk menyatakan menyebabkannya hanya mengembalikan nama fungsi yang ditemukan, daripada seluruh konten.
Seharusnya tidak ada penalti kinerja yang terukur untuk penggunaan / dev / null, dan jika itu membuat Anda sangat khawatir:
Atau kombinasikan keduanya, untuk kesenangan tak berguna Anda sendiri. Keduanya bekerja.
sumber
-F
pilihan des tidak ada dalam zsh (berguna untuk portabilitas)-F
juga tidak perlu benar-benar: tampaknya menekan definisi fungsi / tubuh saja.cat "$fn" | wc -c
? Sedangkan untuk zsh, jika tag bash tidak memberi tahu Anda, mungkin pertanyaan itu seharusnya ada. + Msgstr "Tentukan apakah suatu fungsi ada di bash". Saya lebih lanjut akan menunjukkan, bahwa sementara-F
opsi tidak ada di zsh, itu juga tidak menyebabkan kesalahan, oleh karena itu penggunaan kedua -f dan -F memungkinkan cek berhasil di kedua zsh dan bash yang jika tidak maka tidak akan .-F
digunakan dalam zsh untuk angka floating point. Saya tidak mengerti mengapa menggunakan-F
membuatnya lebih baik di bash ?! Saya mendapat kesan yangdeclare -f
bekerja sama di bash (mengenai kode pengembalian).Meminjam dari solusi dan komentar lain, saya datang dengan ini:
Digunakan sebagai ...
Ia memeriksa apakah argumen yang diberikan adalah fungsi, dan menghindari pengalihan dan grepping lainnya.
sumber
[ $(type -t "$1")"" == 'function' ]
[[...]]
alih-alih,[...]
dan singkirkan retas kutipan. Garpu backticks, yang lambat. Gunakandeclare -f $1 > /dev/null
sebagai gantinya.fn_exists() { [ x$(type -t $1) = xfunction ]; }
Pengerukan pos lama ... tapi saya baru-baru ini menggunakan ini dan menguji kedua alternatif yang dijelaskan dengan:
ini dihasilkan:
menyatakan adalah helluvalot lebih cepat!
sumber
test_type_nogrep () { a () { echo 'a' ;}; local b=$(type a); c=${b//is a function/}; [ $? = 0 ] && return 1 || return 0; }
type
dandeclare
. Dibandingkantype | grep
dengandeclare
. Ini perbedaan besar.Itu bermuara menggunakan 'menyatakan' baik untuk memeriksa output atau kode keluar.
Gaya keluaran:
Pemakaian:
Namun, jika memori berfungsi, pengalihan ke null lebih cepat daripada substitusi output (berbicara tentang, metode `cmd` yang mengerikan dan ketinggalan zaman harus dibuang dan $ (cmd) digunakan sebagai gantinya.) Dan karena menyatakan mengembalikan benar / salah jika ditemukan / tidak ditemukan, dan fungsi mengembalikan kode keluar dari perintah terakhir dalam fungsi sehingga pengembalian eksplisit biasanya tidak diperlukan, dan karena memeriksa kode kesalahan lebih cepat daripada memeriksa nilai string (bahkan string nol):
Keluar dari gaya status:
Itu mungkin tentang singkat dan jinak yang Anda bisa dapatkan.
sumber
isFunction() { declare -F "$1"; } >&-
isFunction() { declare -F -- "$@" >/dev/null; }
adalah rekomendasi saya. Ia bekerja pada daftar nama juga (hanya berhasil jika semua fungsi), tidak memberikan masalah dengan nama yang dimulai dengan-
dan, di sisi saya (bash
4.2.25),declare
selalu gagal ketika output ditutup dengan>&-
, karena tidak dapat menulis nama untuk stdout dalam kasus ituecho
kadang-kadang bisa gagal dengan "panggilan sistem terputus" pada beberapa platform. Dalam hal itu "centang && gema ya || gema tidak" masih dapat menampilkanno
apakahcheck
itu benar.Menguji berbagai solusi:
output misalnya:
Jadi
declare -F f
sepertinya menjadi solusi terbaik.sumber
declare -F f
tidak mengembalikan nilai non-nol jika f tidak ada di zsh, tetapi bash ya. Hati-hati menggunakannya.declare -f f
, dengan tangan lain, berfungsi seperti yang diharapkan melampirkan definisi fungsi pada stdout (yang dapat mengganggu ...)test_type3 () { [[ $(type -t f) = function ]] ; }
ada biaya marjinal untuk menentukan var lokal (walaupun <10%)Dari komentar saya pada jawaban lain (yang saya lewatkan saat kembali ke halaman ini)
sumber
memperbarui
sumber
Saya akan meningkatkannya menjadi:
Dan gunakan seperti ini:
sumber
Ini memberi tahu Anda jika ada, tetapi bukan berarti itu adalah fungsi
sumber
Saya sangat menyukai solusi dari Grégory Joseph
Tetapi saya telah memodifikasinya sedikit untuk mengatasi "trik jelek kutipan ganda":
sumber
Dimungkinkan untuk menggunakan 'ketik' tanpa perintah eksternal, tetapi Anda harus memanggilnya dua kali, sehingga masih berakhir sekitar dua kali lebih lambat dari versi 'nyatakan':
Plus ini tidak berfungsi di POSIX sh, jadi itu sama sekali tidak berharga kecuali sebagai hal sepele!
sumber