Hàm đóng vai trò quan trọng trong mọi ngôn ngữ lập trình. Giống nhiều ngôn ngữ thực sự, bash có hàm với triển khai hạn chế.
Hàm là gì?
Trong lập trình, hàm là các đoạn mã được đặt tên thực hiện tác vụ cụ thể. Trong nghĩa này, hàm là một loại thủ tục hoặc routine. Khi hàm được gọi, chương trình rời khỏi đoạn mã hiện tại và bắt đầu thực thi dòng đầu tiên bên trong hàm. Bất cứ khi nào có mã lặp lại hoặc tác vụ lặp lại, hãy cân nhắc dùng hàm.
Ví dụ, khi cần tìm giai thừa của số ở nhiều giai đoạn trong chương trình. Thay vì viết toàn bộ mã tính giai thừa mỗi lần, viết phần đó một lần trong khối và tái sử dụng nhiều lần.
Tại sao viết hàm?
- Giúp tái sử dụng mã.
- Cải thiện tính đọc được của chương trình.
- Sử dụng biến hiệu quả trong chương trình.
- Cho phép kiểm tra chương trình từng phần.
- Hiển thị chương trình như một loạt các bước con.
Hàm trong shell script
Cú pháp chung viết hàm trong shell script bao gồm các cách sau:
function func_name {
... commands ...
}
hoặc
func_name ( ) {
... commands ...
}
Ngoặc mở cũng có thể ở dòng thứ hai:
func_name ( ) {
... commands ...
}
Bạn tự do viết lệnh hợp lệ bên trong khối hàm như bình thường. Thử viết script đơn giản với hàm nhỏ bên trong.
#!/bin/bash
call_echo ( ) {
echo 'This is inside function'
}
op=$1
if [ $# -ne 1 ]; then
echo "Usage: $0 <1/0>"
else
if [ $1 = 0 ] ; then
echo 'This is outside function'
elif [ $1 = 1 ] ; then
call_echo
else
echo 'Invalid argument'
fi
fi
exit 0
Định nghĩa hàm phải đặt trước lời gọi đầu tiên. Không có khái niệm 'khai báo hàm' trước khi gọi. Và luôn có thể lồng hàm trong hàm.
Lưu ý:- Viết hàm rỗng luôn dẫn đến lỗi cú pháp.
Khi cùng một hàm được định nghĩa nhiều lần, phiên bản cuối cùng là cái được gọi. Ví dụ:
#!/bin/bash
func_same ( ) {
echo 'First definition'
}
func_same ( ) {
echo 'Second definition'
}
func_same
exit 0
Hàm nhận tham số và trả về giá trị
Hãy đi sâu hơn với hàm nhận tham số và trả về giá trị. Để trả về giá trị từ hàm, dùng builtin 'return'. Cú pháp:
func_name ( ) {
... commands ...
return $ret_val
}
Tương tự, truyền tham số cho hàm cách nhau bằng dấu cách:
func_name $arg_1 $arg_2 $arg_3
Bên trong hàm truy cập tham số theo thứ tự $1, $2, $3... Xem script tìm max của 2 số nguyên dùng hàm:
#!/bin/bash
USG_ERR=7
max_two ( ) {
if [ "$1" -eq "$2" ] ; then
echo 'Equal'
exit 0
elif [ "$1" -gt "$2" ] ; then
echo $1
else
echo $2
fi
}
err_str ( ) {
echo "Usage: $0 <number1> <number2>"
exit $USG_ERR
}
NUM_1=$1
NUM_2=$2
x
if [ $# -ne 2 ] ; then
err_str
elif [ `expr $NUM_1 : '[0-9]*'` -eq ${#NUM_1} ] ; then
if [ `expr $NUM_2 : '[0-9]*'` -eq ${#NUM_2} ] ; then
max_two $NUM_1 $NUM_2
else
err_str
fi
else
err_str
fi
exit 0
Trông hơi phức tạp nhưng đơn giản nếu đọc kỹ. Các if-else lồng nhau đầu tiên để validation: kiểm tra số lượng và kiểu tham số với regex. Sau đó gọi hàm với 2 đối số dòng lệnh và hiển thị kết quả tại chỗ. Vì không thể trả về số nguyên lớn từ hàm. Cách khác là dùng biến toàn cục lưu kết quả bên trong hàm. Script dưới minh họa phương pháp này.
#!/bin/bash
USG_ERR=7
ret_val=
max_two ( ) {
if [ "$1" -eq "$2" ] ; then
echo 'Equal'
exit 0
elif [ "$1" -gt "$2" ] ; then
ret_val=$1
else
ret_val=$2
fi
}
err_str ( ) {
echo "Usage: $0 <number1> <number2>"
exit $USG_ERR
}
NUM_1=$1
NUM_2=$2
if [ $# -ne 2 ] ; then
err_str
elif [ `expr $NUM_1 : '[0-9]*'` -eq ${#NUM_1} ] ; then
if [ `expr $NUM_2 : '[0-9]*'` -eq ${#NUM_2} ] ; then
max_two $NUM_1 $NUM_2
echo $ret_val
else
err_str
fi
else
err_str
fi
exit 0
Bây giờ hãy thử một số bài toán thú vị đã giải thích ở series trước dùng hàm:
- Hiểu Basic Linux Shell Scripting Language Tips – Phần I
- 5 Shell Scripts cho Linux Newbies học Shell Programming – Phần II
- Khám phá thế giới Linux BASH Scripting – Phần III
- Khía cạnh Toán học của Linux Shell Programming – Phần IV
- Tính toán biểu thức toán học trong Shell Scripting Language – Phần V
Sẽ quay lại với thêm hiểu sâu về tính năng hàm như biến cục bộ, đệ quy trong phần tới. Cập nhật qua bình luận.