ตัวแปร 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='
'