ค้นหาเว็บไซต์

เจาะลึกลงไปในความซับซ้อนของฟังก์ชันด้วย Shell Scripting – ตอนที่ 7


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

ตัวแปรท้องถิ่น

อะไรทำให้ตัวแปรท้องถิ่น? ขึ้นอยู่กับบล็อกนั้น ๆ ที่มีการประกาศตัวแปร ตัวแปรที่ประกาศเป็น ท้องถิ่น จะสามารถเข้าถึงได้จากบล็อกของโค้ดที่ปรากฏขึ้น กล่าวคือ ขอบเขตของมันคือท้องถิ่น เพื่ออธิบายสิ่งนี้ เรามาดูตัวอย่างด้านล่างกัน

#!/bin/bash 

func( ) { 
	local i=10 
	j=20 
	echo "i from func = $i" 
	echo "j from func = $j" 
} 

echo "i outside func = $i" 
echo "j outside func = $j" 

func 

echo "i outside func = $i" 
echo "j outside func = $j" 

exit 0

เมื่อรันสคริปต์ข้างต้นผลลัพธ์จะเป็น

i outside func = 
j outside func = 
i from func = 10 
j from func = 20 
i outside func = 
j outside func = 20

เนื่องจากฟังก์ชัน func ยังไม่ได้ถูกเรียกในขณะที่คำสั่ง 2 แรก echo ถูกดำเนินการ หลังจากการเรียกใช้ฟังก์ชัน func แล้ว 2 คำสั่ง echo เดียวกันจะให้ผลลัพธ์ที่แตกต่างออกไป ตอนนี้ตัวแปร j ซึ่งได้รับการประกาศภายใน func ไม่ใช่ในเครื่อง สามารถเข้าถึงได้ในภายหลัง

ดังนั้นค่าของ j จะกลายเป็น 20 แล้วตัวแปรท้องถิ่น i ล่ะ? เนื่องจากขอบเขตอยู่ภายในฟังก์ชัน func ค่า 10 ไม่สามารถเข้าถึงได้จากภายนอก โปรดทราบว่าตัวแปร j ที่ปกติจะประกาศภายใน func จะเป็นตัวแปรโกลบอลตามค่าเริ่มต้น

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

การเรียกซ้ำคืออะไร?

ฟังก์ชั่นที่เรียกตัวเองโดยทั่วไปเรียกว่าเป็นขั้นตอนการเรียกซ้ำ หรืออาจนิยามว่าเป็นการแสดงอัลกอริทึมโดยใช้เวอร์ชันที่ง่ายกว่าของอัลกอริทึมเดียวกันนั้น ลองพิจารณาตัวอย่างการหาแฟกทอเรียลของตัวเลข เรารู้ว่า น!=1 x 2 x 3 x … x (n-1) xn. ดังนั้นเราสามารถเขียนความสัมพันธ์ที่เกิดซ้ำได้ดังนี้:

n! = (n-1)! x n

ดังนั้นจึงง่ายสำหรับเราที่จะเรียกใช้ฟังก์ชันเดิมซ้ำๆ และใช้ค่าที่ส่งคืนจากการเรียกแต่ละครั้งเพื่อคูณกับผลลัพธ์ก่อนหน้า เช่น

5! = 4! x 5
4! = 3! x 4
3! = 2! x 3
2! = 1! x 2
1! = 0! x 1

การเรียกซ้ำโดยใช้ตัวแปรท้องถิ่น

ที่นี่เราพยายามเขียนสคริปต์เพื่อค้นหาแฟกทอเรียลของตัวเลขโดยใช้ตัวแปรท้องถิ่นและการเรียกซ้ำ

#!/bin/bash 

fact( ) { 
	local num=$1 
	if [ $num -eq 0 ]; then 
		ret=1 
	else 
		temp=$((num-1)) 
		fact $temp 
		ret=$((num*$?)) 
	fi 
	return $ret 
} 

fact 5 

echo "Factorial of 5 = $?" 

exit 0

num เป็นตัวแปรท้องถิ่นที่ใช้เก็บค่า n-1 แต่ละค่าในการเรียกแต่ละครั้ง เงื่อนไขฐานนี้จะตรวจสอบว่าตัวเลขมีค่าเท่ากับศูนย์หรือไม่ (เนื่องจาก 0!=1 และไม่ได้กำหนดแฟกทอเรียลสำหรับจำนวนลบ) เมื่อมาถึงเงื่อนไขฐานนี้ มันจะคืนค่า 1 ให้กับผู้เรียก ตอนนี้ num=1 และ ret=1 x 1

ในขณะนี้ มันจะส่งกลับ 1 ไปยังผู้เรียก ตอนนี้ num=2 และ ret=2 x 1 ไปเรื่อยๆ สุดท้ายเมื่อ num=5 ค่าที่ส่งคืนจะเป็น 24 และผลลัพธ์สุดท้ายคือ ret=5 x 24 ผลลัพธ์สุดท้าย 120 จะถูกส่งต่อไปยังคำสั่งผู้โทรเริ่มต้นและจะปรากฏขึ้น

มีปัญหาอย่างหนึ่งในสคริปต์ด้านบน ตามที่ฉันได้อธิบายไว้ในบทความที่แล้ว ฟังก์ชันไม่สามารถส่งคืนจำนวนเต็มจำนวนมากได้ ดังนั้นจึงเหลือให้ผู้ใช้ค้นหาวิธีแก้ปัญหาสำหรับปัญหาข้างต้น

ถาม เราสามารถทำการเรียกซ้ำโดยไม่ใช้ตัวแปรท้องถิ่นได้หรือไม่ คำตอบคือใช่

การเรียกซ้ำโดยไม่มีตัวแปรท้องถิ่น

ดูตัวอย่างต่อไปนี้สำหรับการแสดง ชุด Fibonacci โดยใช้การเรียกซ้ำ ความสัมพันธ์การเกิดซ้ำขั้นพื้นฐานคือ:

fib(0) = 0 
fib(1) = 1 
else 
	fib(n) = fib(n-1) + fib(n-2)

Fibonacci series using recursion

#!/bin/bash 

fib( ) { 
	a=$1 
	if [ $a -lt 2 ]; then 
		echo $a 
	else 
		((--a)) 
		b=$(fib $a) 

		((--a)) 
		c=$(fib $a) 

		echo $((b+c)) 
	fi 
} 

for i in $(seq 0 15) 
do 
	out=$(fib $i) 
	echo $out 
done 

exit 0

ไม่มีการใช้ตัวแปรท้องถิ่นในสคริปต์ด้านบน ฉันหวังว่าคุณจะเข้าใจการไหลของสคริปต์ระหว่างการดำเนินการ

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

ในบทความนี้ ฉันวางแผนที่จะสรุปส่วนฟังก์ชันในการเขียนสคริปต์เชลล์ ติดตามข่าวสารล่าสุดกับ Tecmint เพื่ออ่านบทความเกี่ยวกับ arrays และอื่นๆ อีกมากมายเร็วๆ นี้