Saya pikir salah satu cara untuk mencetak informasi tentang fungsi, ketika Anda
uji argumen yang diperlukan dan keluar jika tidak ada - dan tampilkan beberapa pesan
adalah mengubah bash builtin return
dan / atau exit
di awal setiap skrip (atau dalam beberapa file, yang Anda sumber setiap kali sebelum menjalankan program). Jadi, Anda mengetik
#!/bin/bash
return () {
if [ -z $1 ] ; then
builtin return
else
if [ $1 -gt 0 ] ; then
echo function ${FUNCNAME[1]} returns status $1
builtin return $1
else
builtin return 0
fi
fi
}
foo () {
[ 1 != 2 ] && return 1
}
foo
Jika Anda menjalankan ini, Anda akan mendapatkan:
function foo returns status 1
Itu mungkin mudah diperbarui dengan bendera debugging jika Anda perlu, agak seperti ini:
#!/bin/bash
VERBOSE=1
return () {
if [ -z $1 ] ; then
builtin return
else
if [ $1 -gt 0 ] ; then
[ ! -z $VERBOSE ] && [ $VERBOSE -gt 0 ] && echo function ${FUNCNAME[1]} returns status $1
builtin return $1
else
builtin return 0
fi
fi
}
Pernyataan cara ini akan dieksekusi hanya ketika variabel VERBOSE diatur (setidaknya itulah cara saya menggunakan verbose dalam skrip saya). Ini tentu tidak menyelesaikan masalah fungsi dekorasi, tetapi dapat menampilkan pesan jika fungsi mengembalikan status tidak nol.
Demikian pula Anda dapat mendefinisikan ulang exit
, dengan mengganti semua instance return
, jika Anda ingin keluar dari skrip.
EDIT: Saya ingin menambahkan di sini cara saya gunakan untuk menghias fungsi di bash, jika saya punya banyak dari mereka dan yang bersarang juga. Ketika saya menulis skrip ini:
#!/bin/bash
outer () { _
inner1 () { _
print "inner 1 command"
}
inner2 () { _
double_inner2 () { _
print "double_inner1 command"
}
double_inner2
print "inner 2 command"
}
inner1
inner2
inner1
print "just command in outer"
}
foo_with_args () { _ $@
print "command in foo with args"
}
echo command in body of script
outer
foo_with_args
Dan untuk hasilnya saya bisa mendapatkan ini:
command in body of script
outer:
inner1:
inner 1 command
inner2:
double_inner2:
double_inner1 command
inner 2 command
inner1:
inner 1 command
just command in outer
foo_with_args: 1 2 3
command in foo with args
Dapat bermanfaat bagi seseorang yang memiliki fungsi dan ingin men-debugnya, untuk melihat kesalahan fungsi yang terjadi. Ini didasarkan pada tiga fungsi, yang dapat dijelaskan di bawah ini:
#!/bin/bash
set_indentation_for_print_function () {
default_number_of_indentation_spaces="4"
# number_of_spaces_of_current_function is set to (max number of inner function - 3) * default_number_of_indentation_spaces
# -3 is because we dont consider main function in FUNCNAME array - which is if your run bash decoration from any script,
# decoration_function "_" itself and set_indentation_for_print_function.
number_of_spaces_of_current_function=`echo ${#FUNCNAME[@]} | awk \
-v default_number_of_indentation_spaces="$default_number_of_indentation_spaces" '
{ print ($1-3)*default_number_of_indentation_spaces}
'`
# actual indent is sum of default_number_of_indentation_spaces + number_of_spaces_of_current_function
let INDENT=$number_of_spaces_of_current_function+$default_number_of_indentation_spaces
}
print () { # print anything inside function with proper indent
set_indentation_for_print_function
awk -v l="${INDENT:=0}" 'BEGIN {for(i=1;i<=l;i++) printf(" ")}' # print INDENT spaces before echo
echo $@
}
_ () { # decorator itself, prints funcname: args
set_indentation_for_print_function
let INDENT=$INDENT-$default_number_of_indentation_spaces # we remove def_number here, because function has to be right from usual print
awk -v l="${INDENT:=0}" 'BEGIN {for(i=1;i<=l;i++) printf(" ")}' # print INDENT spaces before echo
#tput setaf 0 && tput bold # uncomment this for grey color of decorator
[ $INDENT -ne 0 ] && echo "${FUNCNAME[1]}: $@" # here we avoid situation where decorator is used inside the body of script and not in the function
#tput sgr0 # resets grey color
}
Saya mencoba untuk menempatkan sebanyak mungkin dalam komentar, tapi di sini juga deskripsi: Saya menggunakan _ ()
fungsi sebagai dekorator, yang saya diletakkan setelah deklarasi setiap fungsi: foo () { _
. Fungsi ini mencetak nama fungsi dengan lekukan yang tepat, tergantung seberapa dalam fungsi dalam fungsi lain (sebagai lekukan standar saya menggunakan 4 jumlah spasi). Saya biasanya mencetak ini dalam warna abu-abu, untuk memisahkan ini dari cetakan yang biasa. Jika fungsi perlu didekorasi dengan argumen, atau tanpa argumen, seseorang dapat memodifikasi baris pra-terakhir dalam fungsi dekorator.
Untuk mencetak sesuatu di dalam fungsi, saya memperkenalkan print ()
fungsi yang mencetak semua yang diteruskan dengan indentasi yang tepat.
Fungsi set_indentation_for_print_function
tidak persis apa artinya, menghitung lekukan dari ${FUNCNAME[@]}
array.
Cara ini memiliki beberapa kekurangan, misalnya seseorang tidak dapat melewatkan opsi untuk print
suka echo
, misalnya -n
atau -e
, dan juga jika fungsi mengembalikan 1, itu tidak dihiasi. Dan juga untuk argumen, diteruskan ke print
lebih dari lebar terminal, yang akan dibungkus di layar, orang tidak akan melihat lekukan untuk garis yang dibungkus.
Cara terbaik untuk menggunakan dekorator ini adalah dengan meletakkannya di file terpisah dan di setiap skrip baru untuk sumber file ini source ~/script/hand_made_bash_functions.sh
.
Saya pikir cara terbaik untuk menggabungkan fungsi dekorator dalam bash, adalah dengan menulis dekorator dalam tubuh masing-masing fungsi. Saya pikir itu jauh lebih mudah untuk menulis fungsi di dalam fungsi dalam bash, karena memiliki opsi untuk mengatur semua variabel global, tidak seperti di Bahasa Berorientasi Objek standar. Itu membuatnya seolah-olah Anda menempatkan label di sekitar kode Anda di bash. Setidaknya itu membantu saya untuk skrip debugging.