สำหรับลูปใน zsh และ bash


57

ฉันได้สังเกตว่ามีสองวิธีในการสร้างลูปในzsh :

  1. for x (1 2 3); do echo $x; done
  2. for x in 1 2 3; do echo $x; done

พวกเขาทั้งสองพิมพ์:

1
2
3

คำถามของฉันคือทำไมทั้งสองไวยากรณ์ มีการ$xทำซ้ำผ่านที่แตกต่างกันชนิดของวัตถุในแต่ละของพวกเขา?

ไม่ทุบตีทำให้ความแตกต่างที่คล้ายกัน?

ภาคผนวก:

ทำไมงานต่อไปนี้:

#!/bin/zsh
a=1
b=2
c=5    

d=(a b c)    
for x in $d; do print $x;done

แต่อันนี้ไม่ได้:

#!/bin/zsh
a=1
b=2
c=5

d=(a b c)    
# It complains with "parse error near `$d'"
for x $d; do print $x;done 

5
สำหรับตัวอย่างที่ "ไม่ทำงาน" ซึ่งเป็นรูปแบบcshสำหรับลูปคุณไม่มีวงเล็บอยู่ for x ($d); do print $x; doneจะใช้งานได้และจะจับคู่กับไวยากรณ์แรกที่คุณระบุเมื่อเริ่มต้นคำถาม
Tim Kennedy

1
มันบ้ามาก - ทั้งสองประโยค - ไม่ได้ทั้งคู่ "ทำงานเหมือนกัน" แท้จริงฉันไม่สามารถเอาหัวของฉันไปรอบ ๆ มัน! ฉันต้องการสูบสิ่งที่นักออกแบบเปลือกหอยเหล่านั้นสูบบุหรี่ 'ย้อนกลับไปในวันนี้ฮ่า ๆ
alex grey

ระวังเรื่องนี้มีมากกว่าเรื่องที่ปรากฏในตอนแรก ฉันเชิญคุณตรวจสอบคำตอบของฉัน
jasonleonhard

ฉันไม่เห็นคนอื่นพูดถึงมัน แต่ทั้งสองรูปแบบที่ช่วยให้งดทำ / ทำ: =for i ({0..4..2}) for j ({a..c}) echo "($i,$j)" {0,2,4}x{a,b,c}อัฒภาคนำไปใช้กับวงสุดและเปลี่ยนเส้นทางนำไปใช้กับด้านในสุดและถ้าคุณต้องการที่จะเปลี่ยนที่คุณต้องการเพียงวงเล็บ: =for i ({0..4..2}) { for j ({a..c}) echo "($i,$j)" } | cat -n {1,...,9}*({0,2,4}x{a,b,c})แน่นอนคุณสามารถรวมลูปเข้ากับการขยาย zsh:for i ("("{0..4..2}","{a..c}")") echo $i
John P

คำตอบ:


58

คำสั่งที่ซับซ้อนหลายรูปแบบเช่นลูปมีรูปแบบอื่นใน zsh แบบฟอร์มเหล่านี้ส่วนใหญ่ได้รับแรงบันดาลใจจากC เชลล์ซึ่งเป็นเรื่องธรรมดาเมื่อ zsh ยังเด็ก แต่ตอนนี้ได้หายไป รูปแบบอื่น ๆ เหล่านี้ทำหน้าที่เหมือนกับรูปแบบปกติพวกเขาเป็นเพียงรูปแบบที่แตกต่างกัน มันสั้นกว่าเล็กน้อย แต่มีความชัดเจนน้อยกว่า

รูปแบบมาตรฐานสำหรับforคำสั่งfor x in 1 2 3; do echo $x; doneและแบบฟอร์มมาตรฐานสำหรับคำสั่งwhile while test …; do somecommand; doneKsh, bash และ zsh มีรูปแบบอื่นของfor: for ((i = 0; i < 42; i++)); do somecommand; doneซึ่งเลียนแบบforลูปของภาษาเช่น Pascal หรือ C เพื่อระบุจำนวนเต็ม รูปแบบที่แปลกใหม่อื่น ๆ ที่มีอยู่ใน zsh เฉพาะสำหรับ zsh (แต่มักจะได้รับแรงบันดาลใจจาก csh)


ขอบคุณมาก @ Guilles ฉันยังสับสนอยู่เล็กน้อย ซึ่งรูปแบบเป็นหนึ่งที่เฉพาะเจาะจงเพื่อzsh? นอกจากนี้ฉันได้เพิ่มตัวอย่างหนึ่งที่ส่วนท้ายของ OP ของฉันที่ฉันไม่สามารถหาวิธีการแปลระหว่างไวยากรณ์ หากความแตกต่างเป็นเพียงไวยากรณ์ฉันจะแก้ไขสคริปต์ที่สองในภาคผนวกเพื่อให้ทำงานได้อย่างไร
Amelio Vazquez-Reina

3
@intrpc ดูคำตอบที่อัปเดตของฉัน ในฐานะที่เป็นตัวอย่างล่าสุดของคุณก็ไม่ได้ทำงานเพราะคุณเขียนfor x $dและ zsh คาดว่าอย่างใดอย่างหนึ่งinหรือที่คุณเขียน( $dเครื่องหมายวรรคตอนและคำสงวนไม่สามารถมาจากการขยายตัวตัวแปรพวกเขาจะต้องมีการแยกวิเคราะห์ก่อนที่เปลือกสามารถเริ่มต้นในการขยายตัวแปร
Gilles 'หยุดชั่วร้าย'

@intrpc ทั้งสองเป็น zsh เฉพาะ zsh ได้รับการออกแบบมาโดยเฉพาะเพื่อรองรับทั้งไวยากรณ์ bourne, korn และ c-shell เนื่องจากเป็นลูกผสมของทั้งสาม
ทิมเคนเนดี้

1
@pseyfert ใช้งานได้ แต่ไม่มีประโยชน์ใด ๆ จากแบบฟอร์มที่แสดง: มันพกพาได้น้อยกว่าfor (( … ))แบบฟอร์มและใช้หน่วยความจำจำนวนมากหาก 3 มีขนาดใหญ่
Gilles 'หยุดชั่วร้าย'

1
@ alpha_989 ในไวยากรณ์การดวลจุดโทษเหมือนที่คุณต้องการหลังdo ));Zsh ยังยอมรับไวยากรณ์อื่นfor ((…)); COMMANDซึ่งCOMMANDเป็นคำสั่งเดียว for ((i = 1; i<100; i++)); ghi show $i | grep "log"นั่นเป็นเหตุผลที่จะยอมรับ เมื่อเห็นdoneสิ่งนี้มันบ่นเพราะไม่มีdoที่สิ้นสุด ดู“รูปแบบทางเลือกสำหรับคำสั่งที่ซับซ้อน” ในคู่มือ
Gilles 'ดังนั้นหยุดความชั่วร้าย'
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.