ตัวแปร unquote (ใน$var
) หรือการทดแทนคำสั่ง (ใน$(cmd)
หรือ`cmd`
) เป็นตัวดำเนินการแยก + globในเชลล์คล้ายบอร์น
นั่นคือเนื้อหาจะแบ่งตามค่าปัจจุบันของ$IFS
ตัวแปรพิเศษ (ซึ่งโดยค่าเริ่มต้นจะมีช่องว่างแท็บและอักขระขึ้นบรรทัดใหม่)
และแต่ละคำที่เป็นผลมาจากการแยกนั้นจะขึ้นอยู่กับการสร้างชื่อไฟล์ (หรือที่รู้จักกันในชื่อการขยายแบบวงกลมหรือชื่อไฟล์ ) นั่นคือพวกเขาถูกพิจารณาว่าเป็นรูปแบบและขยายไปยังรายการไฟล์ที่ตรงกับรูปแบบนั้น
ดังนั้นในfor i in $(xrandr)
การ$(xrandr)
เพราะมันไม่ได้อยู่ในคำพูดเป็นแยกลำดับของพื้นที่แท็บและตัวอักษรขึ้นบรรทัดใหม่ และแต่ละคำที่เป็นผลมาจากการแยกนั้นจะถูกตรวจสอบเพื่อหาชื่อไฟล์ที่ตรงกัน (หรือปล่อยทิ้งไว้ราวกับว่าพวกเขาไม่ตรงกับไฟล์ใด ๆ ) และfor
วนซ้ำทั้งหมด
ในfor i in "$(xrandr)"
เราไม่ได้ใช้ตัวดำเนินการแยก + glob เนื่องจากมีการอ้างอิงคำสั่งแทนที่ดังนั้นจึงมีหนึ่งรอบในการวนรอบหนึ่งค่า: ผลลัพธ์ของxrandr
(โดยไม่มีอักขระขึ้นบรรทัดใหม่ที่ต่อท้ายซึ่งแทนที่แถบคำสั่ง )
อย่างไรก็ตามในecho $i
, $i
เป็น unquoted อีกครั้งอีกครั้งเนื้อหาของ$i
ถูกแบ่งและอาจมีการสร้างชื่อไฟล์และผู้ที่จะถูกส่งผ่านเป็นอาร์กิวเมนต์แยกต่างหากกับecho
คำสั่ง (และecho
ข้อโต้แย้งของเอาท์พุทคั่นด้วยช่องว่าง)
บทเรียนจึงได้เรียนรู้:
- หากคุณไม่ต้องการให้มีการแยกคำหรือสร้างชื่อไฟล์ให้อ้างอิงการขยายตัวแปรและการแทนที่คำสั่งเสมอ
- หากคุณต้องการแบ่งคำหรือสร้างชื่อไฟล์ให้ปล่อยไว้โดยไม่ต้องยกมา แต่ตั้ง
$IFS
ตามและ / หรือเปิดหรือปิดการสร้างชื่อไฟล์ถ้าจำเป็น ( set -f
, set +f
)
โดยปกติในตัวอย่างของคุณด้านบนหากคุณต้องการวนซ้ำรายการคำที่คั่นด้วยช่องว่างในผลลัพธ์ของxrandr
คุณจะต้อง:
- ปล่อยให้
$IFS
เป็นค่าเริ่มต้น (หรือยกเลิกการตั้งค่า) เพื่อแยกช่องว่าง
- ใช้
set -f
เพื่อปิดใช้งานการสร้างชื่อไฟล์เว้นแต่คุณจะแน่ใจว่าxrandr
จะไม่ส่งออกใด ๆ*
หรือ?
หรือ[
อักขระ (ซึ่งเป็นอักขระตัวแทนที่ใช้ในรูปแบบการสร้างชื่อไฟล์)
จากนั้นให้ใช้ตัวดำเนินการแยก + glob (ปล่อยให้การแทนที่คำสั่งหรือการขยายตัวตัวแปรแบบไม่มีเครื่องหมายเท่านั้น) ในin
ส่วนของfor
ลูป:
set -f; unset -v IFS
for i in $(xrandr); do whatever with "$i"; done
หากคุณต้องการวนซ้ำบรรทัด (ไม่ว่าง) ของxrandr
เอาต์พุตคุณจะต้องตั้งค่า$IFS
เป็นอักขระบรรทัดใหม่:
IFS='
'