การเปลี่ยน IFS ชั่วคราวก่อน a for loop [ซ้ำ]

Aug 16 2020

ฉันรู้ว่าการSHELLอนุญาตให้กำหนดตัวแปรเกิดขึ้นทันทีก่อนคำสั่งซึ่งได้IFS=":" read a b c d <<< "$here_string"ผล ...

สิ่งที่ฉันสงสัยคือการมอบหมายงานดังกล่าวไม่ได้ผลเมื่อทำด้วยคำสั่งประกอบเช่นลูป? ฉันลองทำบางอย่างเช่นIFS=":" for i in $PATH; do echo $i; doneแต่ผลลัพธ์เกิดข้อผิดพลาดทางไวยากรณ์ ฉันสามารถทำสิ่งที่ชอบได้เสมอoldIFS="$IFS"; IFS=":"; for....; IFS="$oldIFS"แต่ฉันต้องการทราบว่ามีวิธีใดบ้างที่ฉันสามารถทำให้การมอบหมายแบบอินไลน์ทำงานสำหรับคำสั่งผสมเช่นforลูปได้หรือไม่?

คำตอบ

3 Quasímodo Aug 16 2020 at 21:12

forเป็นคำสงวนและเป็นไปตามกฎพิเศษ :

คำต่อไปนี้ให้ถือเป็นคำสงวน:

! {} case do elif else esac fi for if in then until while

การรับรู้นี้จะเกิดขึ้นก็ต่อเมื่อไม่มีการยกตัวอักษรใด ๆ และเมื่อใช้คำเป็น:

  • คำแรกของคำสั่ง

  • ครั้งแรกที่คำต่อไปนี้อย่างใดอย่างหนึ่งของคำลิขสิทธิ์อื่น ๆ นอกเหนือจากกรณี , สำหรับหรือใน

  • คำที่สามในคำสั่ง case (เฉพาะในเท่านั้นที่ใช้ได้ในกรณีนี้)

  • คำที่สามในคำสั่ง for (เฉพาะในและdoเท่านั้นที่ใช้ได้ในกรณีนี้)

ถ้าคุณพยายาม

IFS=":" for i in $PATH; do echo $i; done

ตามกฎข้างต้นนั่นไม่ใช่การforวนซ้ำเนื่องจากคีย์เวิร์ดไม่ใช่คำแรกของคำสั่ง แต่ความตั้งใจของคุณสามารถทำได้ด้วย

IFS=: printf '%s\n' $PATH

$PATHได้รับการแบ่งคำ:ตามที่คาดไว้และแต่ละคำที่ได้จะถูกพิมพ์printfตามด้วยขึ้นบรรทัดใหม่


คุณอาจคุ้นเคยกับแนวทางที่ถูกต้องนี้:

while IFS= read -r line; do

whileเป็นคำแรกของคำสั่งและการIFSกำหนดใช้กับreadดังนั้นทุกอย่างก็โอเค