Untuk loop dalam zsh dan bash

57

Saya perhatikan ada dua cara alternatif untuk membangun loop di zsh :

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

Keduanya mencetak:

1
2
3

Pertanyaan saya adalah, mengapa kedua sintaksis itu? Apakah $xiterasi melalui berbagai jenis objek di masing-masing?

Apakah bash membuat perbedaan yang sama?

Tambahan:

Mengapa cara berikut ini berhasil ?:

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

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

tapi yang ini tidak ?:

#!/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 
Amelio Vazquez-Reina
sumber
5
untuk contoh bahwa "tidak bekerja", yang merupakan gaya csh untuk loop, Anda kehilangan tanda kurung. for x ($d); do print $x; doneakan berfungsi, dan itu akan cocok dengan sintaks pertama yang telah Anda sebutkan di awal pertanyaan Anda.
Tim Kennedy
1
Hal ini SO gila - bahwa kedua pernyataan - memang tidak baik "bekerja sama". Saya benar-benar tidak bisa melupakannya! Saya perlu merokok apa yang para perancang kulit itu merokok, 'kembali pada hari itu, lol.
alex grey
Hati-hati, ada lebih banyak cerita ini daripada yang awalnya muncul. Saya mengundang Anda untuk memeriksa jawaban saya.
jasonleonhard
Saya tidak melihat orang lain menyebutkannya, tetapi kedua bentuk tersebut memungkinkan penghapusan do / done: for i ({0..4..2}) for j ({a..c}) echo "($i,$j)"= {0,2,4}x{a,b,c}. Titik koma berlaku untuk loop terluar dan pengalihan berlaku untuk innermost, dan jika Anda perlu mengubahnya, Anda hanya perlu kawat gigi: for i ({0..4..2}) { for j ({a..c}) echo "($i,$j)" } | cat -n= {1,...,9}*({0,2,4}x{a,b,c}). Tentu saja Anda dapat menggabungkan loop dengan ekspansi zsh:for i ("("{0..4..2}","{a..c}")") echo $i
John P

Jawaban:

59

Beberapa bentuk perintah kompleks seperti loop memiliki bentuk alternatif di zsh. Bentuk-bentuk ini sebagian besar terinspirasi oleh shell C , yang cukup umum ketika zsh masih muda tetapi sekarang telah menghilang. Bentuk-bentuk alternatif ini bertindak persis seperti bentuk normal, mereka hanya sintaks yang berbeda. Mereka sedikit lebih pendek, tetapi kurang jelas.

Bentuk standar untuk forperintah adalah for x in 1 2 3; do echo $x; done, dan bentuk standar untuk whileperintah adalah while test …; do somecommand; done. Ksh, bash dan zsh memiliki alternatif bentuk for: for ((i = 0; i < 42; i++)); do somecommand; doneyang meniru forloop bahasa seperti Pascal atau C, untuk menghitung bilangan bulat. Bentuk eksotis lainnya yang ada di zsh adalah khusus untuk zsh (tetapi sering terinspirasi oleh csh).

Gilles 'SANGAT berhenti menjadi jahat'
sumber
Terima kasih banyak @Guilles. Saya masih agak bingung. Bentuk mana yang spesifik untuk zsh? Juga, saya telah menambahkan satu contoh di akhir OP saya di mana saya tidak tahu bagaimana menerjemahkan antar sintaks. Jika perbedaannya hanya sintaks, bagaimana saya harus memperbaiki skrip kedua di addendum agar berfungsi?
Amelio Vazquez-Reina
3
@ intrpc. Lihat jawaban saya yang diperbarui. Adapun contoh terakhir Anda, itu tidak berfungsi karena Anda menulis for x $ddan zsh mengharapkan salah satu inatau di (mana Anda menulis $d. Tanda baca dan kata-kata yang dipesan tidak dapat berasal dari ekspansi variabel, mereka harus diuraikan sebelum shell dapat mulai pada ekspansi variabel.
Gilles 'SANGAT berhenti menjadi jahat'
@ intrpc keduanya khusus zsh. zsh secara khusus dirancang untuk mendukung sintaksis bourne, korn, dan c-shell, karena merupakan hibrida dari ketiganya.
Tim Kennedy
1
@pseyfert Berhasil, tetapi tidak memiliki kelebihan dibandingkan formulir yang saya perlihatkan: ini lebih portabel daripada for (( … ))formulir dan menggunakan banyak memori jika 3 besar.
Gilles 'SANGAT berhenti menjadi jahat'
1
@ alpha_989 Dalam sintaks seperti sh, Anda perlu dosetelah ));. Zsh juga menerima sintaks lain di for ((…)); COMMANDmana COMMANDsatu perintah. Itu sebabnya ia menerima for ((i = 1; i<100; i++)); ghi show $i | grep "log". Ketika ia melihat donesetelah ini, ia mengeluh karena tidak ada doakhir. Lihat “Formulir Alternatif Untuk Perintah Kompleks” di manual .
Gilles 'SANGAT berhenti menjadi jahat'