จุดประสงค์ของคำหลัก "ทำ" ใน Bash สำหรับลูปคืออะไร


76

วัตถุประสงค์ของdoคำหลักในforไวยากรณ์วนซ้ำคืออะไร สำหรับฉันมันรู้สึกซ้ำซ้อน

for i in `seq 1 2`; do echo "hi"; done

ทำไมไวยากรณ์ไม่เป็นแบบนี้

for i in `seq 1 2`; echo "hi"; done

ฉันแน่ใจว่ามันไม่กรอกวัตถุประสงค์ ฉันแค่ต้องการเรียนรู้

คำตอบ:


118

โปรดทราบว่าไวยากรณ์นั้นสืบทอดมาจากเชลล์เป้าหมาย

หลังจากชื่อตัวแปรคุณสามารถมีinรายการขององค์ประกอบที่กำหนดไว้อย่างชัดเจนหรือdoเพื่อวนรอบพารามิเตอร์ตำแหน่ง

for i in 1 2 3
do
  echo "$i"
done

หรือ

set 1 2 3
for i do
  echo "$i"
done

การมีdoทั้งสองกรณี (แม้ว่าจะไม่จำเป็นอย่างยิ่งในกรณีแรก) จะทำให้ไวยากรณ์มีความสอดคล้องกันมากขึ้น นอกจากนี้ยังสอดคล้องกับwhile/ untilลูปที่doจำเป็น

while
  cmd1
  cmd2
do
  cmd3
  cmd4
done

คุณต้องการที่doจะบอกว่ารายการคำสั่งเงื่อนไขสิ้นสุดลงที่ใด

for i; doโปรดทราบว่าเปลือกบอร์นไม่ได้สนับสนุน ไวยากรณ์นั้นยังไม่ได้ POSIX จนกว่ามาตรฐานรุ่นปี 2016 ( for i doเป็น POSIX เสมอดูข้อบกพร่องของกลุ่ม Austin ที่เกี่ยวข้อง )

zsh มีรูปแบบย่อบางอย่างเช่น:

for i in 1 2 3; echo $i
for i (1 2 3) echo $i
for ((i=1;i<=3;i++)) echo $i

หรือสนับสนุนตัวแปรมากกว่าหนึ่งตัว:

for i j (1 a 2 b) echo $i $j

(แม้ว่าคุณจะไม่สามารถใช้inหรือdoเป็นชื่อตัวแปรแทนตำแหน่งjด้านบน)

แม้ว่าไม่ค่อยเอกสารส่วนใหญ่เปลือกหอยบอร์นเหมือน (บอร์ ksh, ทุบตี zsh ไม่ashว่ามิได้yash) นอกจากนี้ยังสนับสนุน:

for i in 1 2 3; { echo "$i";}

เชลล์เป้าหมายkshและzsh(แต่ไม่ใช่bash) รองรับเช่นกัน:

for i { echo "$i"; }

ในขณะที่bash, kshและzsh( แต่ไม่บอร์นเชลล์) การสนับสนุน:

for i; { echo "$i"; }

ทั้งหมด (บอร์นbash, ksh, zsh) การสนับสนุน:

for i
{ echo "$i";}

ksh93, bash, zshการสนับสนุน:

for ((i=1;i<=3;i++)) { echo "$i"; }

2
เช่นเคยคำตอบที่สมบูรณ์และสมบูรณ์แบบ (อ้างอิงถึง zsh) ...
Kiwy

2
มันไม่ได้เป็น "จำเป็นอย่างเคร่งครัด" ทั้งในกรณีfor; คำสั่งอาจถูกยกเลิกโดย newline หรือ semicolon มันค่อนข้างสมเหตุสมผลสำหรับif/ while(อดีตที่มีthenมากกว่าdo) แต่โดยหลักการแล้วผู้ใช้สามารถละเว้นมันและจำเป็นต้องใช้ subshell หรือวงเล็บปีกกาสำหรับการใช้ (คำสั่ง) ที่หายากของคำสั่งหลายรายการ ฉันสงสัยว่าเหตุผลที่แท้จริงว่าเปลือกบอร์นไม่ได้เป็นเพราะ ALGOL ไม่มันและเราควรจะดีใจที่ไม่ได้สะกดdone od
Random832

4
@ Random832: นั่นเป็นเพราะodเคยใช้เป็นชื่อของโปรแกรม Octal Dump แล้ว
user1024

8
มีอะไรมากมายที่ฉันไม่รู้ ขอขอบคุณ!
การแข่งขัน Lightness ใน Orbit

1
@mirabilos for i doเป็น Bourne และ POSIX แต่จะไม่ทำงานใน IIRC เวอร์ชันเก่าที่ใช้ขี้เถ้า for i in "$@"จะไม่ทำงานในเชลล์เป้าหมายหาก$IFSไม่มีอักขระช่องว่าง for i<newline>doแน่นอนพกพามากที่สุดหากคุณต้องการพิจารณาระบบ BSD ที่เก่ามาก ดูรายละเอียดได้ที่in-ulm.de/~mascheck/various/bourne_args
Stéphane Chazelas
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.