Computer >> บทช่วยสอนคอมพิวเตอร์ >  >> การเขียนโปรแกรม >> การเขียนโปรแกรม Bash

เชี่ยวชาญ Bash Functions: สำรวจลึกฟังก์ชันใน Shell Scripting (ตอนที่ 6)

ฟังก์ชันเล่นบทบาทสำคัญในภาษาโปรแกรมใดๆ เหมือนภาษาโปรแกรมจริงหลายภาษา bash มีฟังก์ชันที่ใช้งานได้ด้วยการนำไปปฏิบัติที่จำกัด

ฟังก์ชันคืออะไร?

ในการเขียนโปรแกรม ฟังก์ชันคือส่วนที่มีชื่อของโปรแกรมที่ทำงานเฉพาะเจาะจง ในความหมายนี้ ฟังก์ชันเป็นประเภทหนึ่งของขั้นตอนหรือวันช่าทั่วไป เมื่อฟังก์ชันถูกเรียก โปรแกรมจะออกจากส่วนโค้ดปัจจุบันและเริ่มรันบรรทัดแรกภายในฟังก์ชัน ทุกครั้งที่มีโค้ดซ้ำ หรือเมื่องานซ้ำกัน พิจารณาใช้ฟังก์ชันแทน

ตัวอย่าง กรณีที่เราต้องหาแฟกทอเรียลของตัวเลขในหลายขั้นตอนของโปรแกรมเฉพาะ แทนที่จะเขียนโค้ดทั้งหมด (สำหรับคำนวณแฟกทอเรียล) ทุกครั้ง เราสามารถเขียนส่วนโค้ดที่คำนวณแฟกทอเรียลครั้งเดียวภายในบล็อก และนำไปใช้ซ้ำได้หลายครั้ง

ทำไมเราต้องเขียนฟังก์ชัน?

  1. ช่วยนำโค้ดกลับมาใช้ซ้ำได้
  2. ปรับปรุงความอ่านง่ายของโปรแกรม
  3. ใช้ตัวแปรในโปรแกรมอย่างมีประสิทธิภาพ
  4. อนุญาตให้ทดสอบโปรแกรมทีละส่วน
  5. แสดงโปรแกรมเป็นชุดขั้นตอนย่อย
ฟังก์ชันในเชลล์สคริปต์

ไวยากรณ์ทั่วไปสำหรับการเขียนฟังก์ชันในเชลล์สคริปต์รวมถึงวิธีต่อไปนี้

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

ตอนนี้ลองแก้ปัญหาที่น่าตื่นเต้นซึ่งอธิบายในซีรีส์เชลล์สคริปติ้งก่อนหน้านี้โดยใช้ฟังก์ชันดังนี้

  1. Understand Basic Linux Shell Scripting Language Tips – Part I
  2. 5 Shell Scripts for Linux Newbies to Learn Shell Programming – Part II
  3. Sailing Through The World of Linux BASH Scripting – Part III
  4. Mathematical Aspect of Linux Shell Programming – Part IV
  5. Calculating Mathematical Expressions in Shell Scripting Language – Part V

ผมจะกลับมากับข้อมูลเชิงลึกเพิ่มเติมเกี่ยวกับคุณสมบัติฟังก์ชัน เช่น การใช้ตัวแปร local, recursion เป็นต้น ในส่วนต่อไป ติดตามกันต่อกับความคิดเห็น