ทำไม 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 ในสคริปต์ของคุณได้อย่างมั่นใจเพื่อให้ผลลัพธ์ที่สะอาดและควบคุมได้!

ด้วยการใช้แนวทางปฏิบัติที่ดีที่สุดเช่นนี้ คุณจะพบว่าตัวเองสร้างสคริปต์เชลล์ที่มีความแข็งแกร่งและเชื่อถือได้มากขึ้น.