Tôi nghĩ một cách để in thông tin về chức năng, khi bạn
kiểm tra các đối số cần thiết và thoát nếu chúng không tồn tại - và hiển thị một số thông báo
là để thay đổi bash dựng sẵn return
và / hoặc exit
vào đầu mỗi tập lệnh (hoặc trong một số tệp, mà bạn nguồn mỗi lần trước khi thực hiện chương trình). Vì vậy, bạn gõ
#!/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
Nếu bạn chạy nó, bạn sẽ nhận được:
function foo returns status 1
Điều đó có thể dễ dàng cập nhật với cờ gỡ lỗi nếu bạn cần, hơi giống như thế này:
#!/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
}
Câu lệnh theo cách này sẽ chỉ được thực thi khi đặt ĐỘNG TỪ biến (ít nhất đó là cách tôi sử dụng dài dòng trong tập lệnh của mình). Nó chắc chắn không giải quyết được vấn đề về chức năng trang trí, nhưng nó có thể hiển thị các thông báo trong trường hợp hàm trả về trạng thái khác không.
Tương tự, bạn có thể xác định lại exit
, bằng cách thay thế tất cả các trường hợp return
, nếu bạn muốn thoát khỏi tập lệnh.
EDIT: Tôi muốn thêm vào đây cách tôi sử dụng để trang trí các chức năng trong bash, nếu tôi có rất nhiều trong số chúng và cũng được lồng vào nhau. Khi tôi viết kịch bản này:
#!/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
Và đối với đầu ra tôi có thể nhận được điều này:
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
Nó có thể hữu ích cho ai đó có chức năng và muốn gỡ lỗi chúng, để xem lỗi nào xảy ra. Nó dựa trên ba chức năng, có thể được mô tả dưới đây:
#!/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
}
Tôi đã cố gắng đưa càng nhiều càng tốt trong các bình luận, nhưng đây cũng là mô tả: Tôi sử dụng _ ()
chức năng như trang trí, cái tôi đặt sau khi khai báo mọi chức năng : foo () { _
. Hàm này in tên hàm với thụt lề thích hợp, tùy thuộc vào mức độ sâu của hàm trong hàm khác (như một thụt đầu dòng mặc định tôi sử dụng 4 số khoảng trắng). Tôi thường in cái này bằng màu xám, để tách cái này ra khỏi bản in thông thường. Nếu chức năng là cần thiết để được trang trí bằng các đối số, hoặc không có, người ta có thể sửa đổi dòng trước cuối trong chức năng trang trí.
Để in một cái gì đó bên trong chức năng, tôi đã giới thiệu print ()
chức năng in mọi thứ được truyền cho nó với thụt lề thích hợp.
Hàm set_indentation_for_print_function
thực hiện chính xác những gì nó đại diện cho, tính toán thụt lề từ ${FUNCNAME[@]}
mảng.
Cách này có một số sai sót, ví dụ người ta không thể vượt qua các tùy chọn để print
thích echo
, ví dụ -n
hoặc -e
, và nếu hàm trả về 1, nó không được trang trí. Và cũng đối với các đối số, được chuyển đến print
nhiều hơn độ rộng của thiết bị đầu cuối, sẽ được bao bọc trên màn hình, người ta sẽ không thấy vết lõm cho đường bao bọc.
Cách tuyệt vời để sử dụng các trình trang trí này là đặt chúng vào tệp riêng biệt và trong mỗi tập lệnh mới để lấy nguồn tệp này source ~/script/hand_made_bash_functions.sh
.
Tôi nghĩ rằng cách tốt nhất để kết hợp chức năng trang trí trong bash, là viết trang trí trong cơ thể của từng chức năng. Tôi nghĩ rằng việc viết hàm bên trong hàm trong bash sẽ dễ dàng hơn nhiều, bởi vì nó có tùy chọn để đặt tất cả các biến toàn cục, không giống như trong các Ngôn ngữ hướng đối tượng tiêu chuẩn. Điều đó làm cho nó giống như bạn đang đặt nhãn xung quanh mã của bạn trong bash. Ít nhất điều đó đã giúp tôi cho một kịch bản gỡ lỗi.
typeset
cần thiết không? Nó sẽ không tuyên bố nó khác?