ฟังก์ชันเล่นบทบาทสำคัญในภาษาโปรแกรมใดๆ เหมือนภาษาโปรแกรมจริงหลายภาษา bash มีฟังก์ชันที่ใช้งานได้ด้วยการนำไปปฏิบัติที่จำกัด
ฟังก์ชันคืออะไร?
ในการเขียนโปรแกรม ฟังก์ชันคือส่วนที่มีชื่อของโปรแกรมที่ทำงานเฉพาะเจาะจง ในความหมายนี้ ฟังก์ชันเป็นประเภทหนึ่งของขั้นตอนหรือวันช่าทั่วไป เมื่อฟังก์ชันถูกเรียก โปรแกรมจะออกจากส่วนโค้ดปัจจุบันและเริ่มรันบรรทัดแรกภายในฟังก์ชัน ทุกครั้งที่มีโค้ดซ้ำ หรือเมื่องานซ้ำกัน พิจารณาใช้ฟังก์ชันแทน
ตัวอย่าง กรณีที่เราต้องหาแฟกทอเรียลของตัวเลขในหลายขั้นตอนของโปรแกรมเฉพาะ แทนที่จะเขียนโค้ดทั้งหมด (สำหรับคำนวณแฟกทอเรียล) ทุกครั้ง เราสามารถเขียนส่วนโค้ดที่คำนวณแฟกทอเรียลครั้งเดียวภายในบล็อก และนำไปใช้ซ้ำได้หลายครั้ง
ทำไมเราต้องเขียนฟังก์ชัน?
- ช่วยนำโค้ดกลับมาใช้ซ้ำได้
- ปรับปรุงความอ่านง่ายของโปรแกรม
- ใช้ตัวแปรในโปรแกรมอย่างมีประสิทธิภาพ
- อนุญาตให้ทดสอบโปรแกรมทีละส่วน
- แสดงโปรแกรมเป็นชุดขั้นตอนย่อย
ฟังก์ชันในเชลล์สคริปต์
ไวยากรณ์ทั่วไปสำหรับการเขียนฟังก์ชันในเชลล์สคริปต์รวมถึงวิธีต่อไปนี้
function func_name {
... commands ...
}
or
func_name ( ) {
... commands ...
}
Opening curly braces สามารถวางในบรรทัดที่สองได้เช่นกัน
func_name ( ) {
... commands ...
}
คุณอิสระที่จะเขียนคำสั่งที่ถูกต้องภายในบล็อกฟังก์ชันเหล่านี้เหมือนที่เราทำปกติในเชลล์สคริปต์ ตอนนี้ลองเขียนสคริปต์ง่ายๆ ที่มีฟังก์ชันเล็กๆ อยู่ในนั้น
#!/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
การนิยามฟังก์ชันต้องอยู่ก่อนการเรียกครั้งแรก ไม่มีสิ่งที่เรียกว่า 'การประกาศฟังก์ชัน' ก่อนเรียก และเราสามารถซ้อนฟังก์ชันภายในฟังก์ชันได้เสมอ
หมายเหตุ:- การเขียนฟังก์ชันว่างเปล่าจะทำให้เกิด syntax error เสมอ
เมื่อฟังก์ชันเดียวกันถูกนิยามหลายครั้ง เวอร์ชันสุดท้ายคือสิ่งที่จะถูกเรียกใช้ ลองดูตัวอย่าง
#!/bin/bash
func_same ( ) {
echo 'First definition'
}
func_same ( ) {
echo 'Second definition'
}
func_same
exit 0
ฟังก์ชันที่รับพารามิเตอร์และคืนค่า
ลองเจาะลึกโดยพิจารณาฟังก์ชันที่รับพารามิเตอร์และคืนค่า เพื่อคืนค่าจากฟังก์ชัน เราใช้ 'return' shell built-in ไวยากรณ์ดังนี้
func_name ( ) {
... commands ...
return $ret_val
}
เช่นเดียวกัน เราสามารถส่งอาร์กิวเมนต์ให้ฟังก์ชันคั่นด้วยช่องว่างได้ดังนี้
func_name $arg_1 $arg_2 $arg_3
ภายในฟังก์ชัน เราสามารถเข้าถึงอาร์กิวเมนต์ตามลำดับเป็น $1, $2, $3 และต่อไป ดูสคริปต์ตัวอย่างต่อไปนี้เพื่อหาค่าสูงสุดของจำนวนเต็ม 2 จำนวนโดยใช้ฟังก์ชัน
#!/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 "
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
ดูซับซ้อนนิดหน่อย แต่มันง่ายถ้าอ่านทีละบรรทัด บรรทัด if-else if แรกเป็นการตรวจสอบวัตถุประสงค์ คือ ตรวจสอบจำนวนและประเภทของอาร์กิวเมนต์ด้วย regular expressions หลังจากนั้นเราเรียกฟังก์ชันด้วยอาร์กิวเมนต์บรรทัดคำสั่ง 2 ตัว และแสดงผลที่นั่นเลย เพราะเราไม่สามารถคืนจำนวนเต็มขนาดใหญ่จากฟังก์ชันได้ อีกวิธีหนึ่งคือใช้ตัวแปร global เพื่อเก็บผลลัพธ์ภายในฟังก์ชัน สคริปต์ด้านล่างอธิบายวิธีนี้
#!/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 "
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
ตอนนี้ลองแก้ปัญหาที่น่าตื่นเต้นซึ่งอธิบายในซีรีส์เชลล์สคริปติ้งก่อนหน้านี้โดยใช้ฟังก์ชันดังนี้
- Understand Basic Linux Shell Scripting Language Tips – Part I
- 5 Shell Scripts for Linux Newbies to Learn Shell Programming – Part II
- Sailing Through The World of Linux BASH Scripting – Part III
- Mathematical Aspect of Linux Shell Programming – Part IV
- Calculating Mathematical Expressions in Shell Scripting Language – Part V
ผมจะกลับมากับข้อมูลเชิงลึกเพิ่มเติมเกี่ยวกับคุณสมบัติฟังก์ชัน เช่น การใช้ตัวแปร local, recursion เป็นต้น ในส่วนต่อไป ติดตามกันต่อกับความคิดเห็น