Trong công việc, tôi viết kịch bản bash thường xuyên. Người giám sát của tôi đã đề nghị rằng toàn bộ tập lệnh được chia thành các chức năng, tương tự như ví dụ sau:
#!/bin/bash
# Configure variables
declare_variables() {
noun=geese
count=three
}
# Announce something
i_am_foo() {
echo "I am foo"
sleep 0.5
echo "hear me roar!"
}
# Tell a joke
walk_into_bar() {
echo "So these ${count} ${noun} walk into a bar..."
}
# Emulate a pendulum clock for a bit
do_baz() {
for i in {1..6}; do
expr $i % 2 >/dev/null && echo "tick" || echo "tock"
sleep 1
done
}
# Establish run order
main() {
declare_variables
i_am_foo
walk_into_bar
do_baz
}
main
Có bất kỳ lý do để làm điều này ngoài "khả năng đọc", mà tôi nghĩ có thể được thiết lập tốt như nhau với một vài bình luận và khoảng cách dòng?
Liệu nó làm cho kịch bản chạy hiệu quả hơn (tôi thực sự mong đợi điều ngược lại, nếu có), hoặc nó giúp việc sửa đổi mã dễ dàng hơn ngoài tiềm năng dễ đọc đã nói ở trên? Hay nó thực sự chỉ là một sở thích phong cách?
Xin lưu ý rằng mặc dù tập lệnh không thể hiện tốt, "thứ tự chạy" của các hàm trong tập lệnh thực tế của chúng tôi có xu hướng rất tuyến tính - walk_into_bar
phụ thuộc vào công cụ i_am_foo
đã thực hiện và do_baz
hoạt động trên công cụ được thiết lập bởi walk_into_bar
- vì vậy có thể tự ý trao đổi thứ tự chạy không phải là thứ chúng ta thường làm. Ví dụ, bạn sẽ không đột nhiên muốn đặt declare_variables
sau walk_into_bar
, điều đó sẽ phá vỡ mọi thứ.
Một ví dụ về cách tôi sẽ viết kịch bản trên sẽ là:
#!/bin/bash
# Configure variables
noun=geese
count=three
# Announce something
echo "I am foo"
sleep 0.5
echo "hear me roar!"
# Tell a joke
echo "So these ${count} ${noun} walk into a bar..."
# Emulate a pendulum clock for a bit
for i in {1..6}; do
expr $i % 2 >/dev/null && echo "tick" || echo "tock"
sleep 1
done
local
- điều này cung cấp phạm vi biến cực kỳ quan trọng trong bất kỳ tập lệnh không tầm thường nào.
main()
ở trên cùng và thêmmain "$@"
ở dưới cùng để gọi nó. Điều đó cho phép bạn thấy logic kịch bản cấp cao đầu tiên khi bạn mở nó.