ทำไม Bourne Shell printf
จึงวนซ้ำอาร์กิวเมนต์ %s
?
เมื่อทำงานด้วยสคริปต์เชลล์ โปรแกรมเมอร์หลายคนอาจรู้สึกสับสนกับพฤติกรรมเฉพาะของคำสั่งต่างๆ หนึ่งในกรณีดังกล่าวเกิดขึ้นเมื่อใช้ฟังก์ชัน printf
ใน Bourne shell โดยเฉพาะอย่างยิ่งกับอาร์กิวเมนต์ประเภทสตริง หากคุณเคยพบผลลัพธ์ที่ไม่น่าเชื่อถือขณะพยายามแสดงตัวแปรด้วย printf
คุณไม่ได้อยู่คนเดียว! มาเจาะลึกดูว่าทำไมถึงเกิดเหตุการณ์นี้และจะแก้ไขปัญหาอย่างไร
การวิเคราะห์ปัญหา
ลองพิจารณาสคริปต์เชลล์ง่ายๆ ต่อไปนี้:
#! /bin/sh
NAME="George W. Bush"
printf "Hello, %s\n" $NAME
เมื่อคุณรันสคริปต์นี้ คุณอาจคาดหวังว่าผลลัพธ์จะเป็นดังนี้: Hello, George W. Bush
อย่างไรก็ตาม สิ่งที่คุณเจอคือ:
Hello, George
Hello, W.
Hello, Bush
เกิดอะไรขึ้นที่นี่?
ปัญหาคือการขยายตัวแปรของเชลล์ เมื่อคุณใช้ $NAME
โดยไม่มีเครื่องหมายคำพูด เชลล์จะแยกเนื้อหาของตัวแปร NAME
โดยอิงจากช่องว่าง โดยถือว่าแต่ละส่วนเป็นอาร์กิวเมนต์แยกต่างหาก ดังนั้น printf
จึงถูกเรียกด้วยสามอาร์กิวเมนต์: George
, W.
, และ Bush
แต่ละอันได้รับการประมวลผลเป็นการส่วนตัว ทำให้เกิดพฤติกรรมที่ไม่คาดคิดที่คุณเห็น
วิธีที่ถูกต้อง
เพื่อหลีกเลี่ยงปัญหานี้โดยสิ้นเชิง คุณต้องห่อหุ้มตัวแปรด้วยเครื่องหมายคำพูด นี่คือเวอร์ชันที่ถูกแก้ไขของสคริปต์ของคุณ:
#! /bin/sh
NAME="George W. Bush"
printf "Hello, %s\n" "$NAME"
ทำไมเครื่องหมายคำพูดถึงสำคัญ
เมื่อคุณห่อหุ้ม $NAME
ด้วยเครื่องหมายคำพูด คุณจะบอกเชลล์ว่าทั้งเนื้อหา — รวมถึงช่องว่าง — เป็นอาร์กิวเมนต์เดียว นี่เป็นสิ่งสำคัญสำหรับสตริงที่มีช่องว่าง เนื่องจากจะทำให้มันคงอยู่ในระหว่างการขยายตัวแปร
ตัวเลือกอื่น: ทำไมไม่ใช้ echo
?
คุณอาจสงสัยว่าทำไมคนถึงไม่ใช้ echo
แทน printf
นี่คือการเปรียบเทียบระหว่างสองคำสั่งในบริบทด้วยตัวอย่างที่แตกต่างกัน:
#! /bin/sh
FILE="C:\tmp"
echo "Filename: $FILE"
เมื่อต้องรันสคริปต์นี้ จะให้ผลลัพธ์:
Filename: C: mp
พฤติกรรมนี้แสดงให้เห็นถึงปัญหาที่อาจเกิดขึ้นเมื่อใช้ echo
โดยเฉพาะอย่างยิ่งเกี่ยวกับแบ็คสแลชและลำดับการหลบหลีก ตาม มาตรฐาน POSIX สำหรับ echo
: “ขอแนะนำให้ใช้ printf
แทน echo
สำหรับแอปพลิเคชันใหม่” คำแนะนำนี้ชี้ให้เห็นถึงพฤติกรรมที่คาดการณ์ได้มากขึ้นและความหลากหลายของ printf
ในการจัดรูปแบบผลลัพธ์
สรุป
โดยสรุป สำคัญที่จะต้องจำไว้ว่าขณะใช้ printf
ในสคริปต์เชลล์ ควรใช้เครื่องหมายคำพูดคู่รอบตัวแปรที่อาจมีช่องว่างหรืออักขระพิเศษอยู่เสมอ นี่จะช่วยให้ผลลัพธ์ของคุณทำงานตามที่คาดหวังและหลีกเลี่ยงความประหลาดใจที่น่าหงุดหงิด ด้วยการปรับเปลี่ยนเล็กน้อยนี้ คุณสามารถใช้ printf
ในสคริปต์ของคุณได้อย่างมั่นใจเพื่อให้ผลลัพธ์ที่สะอาดและควบคุมได้!
ด้วยการใช้แนวทางปฏิบัติที่ดีที่สุดเช่นนี้ คุณจะพบว่าตัวเองสร้างสคริปต์เชลล์ที่มีความแข็งแกร่งและเชื่อถือได้มากขึ้น.