Dla pętli w Zsh i Bash

57

Zauważyłem, że istnieją dwa alternatywne sposoby budowania pętli w Zsh :

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

Oba drukują:

1
2
3

Moje pytanie brzmi: dlaczego dwie składnie? Czy w każdym z nich występuje $xiteracja innego typu ?

Czy bash robi podobne rozróżnienie?

Uzupełnienie:

Dlaczego działa następujący:

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

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

ale ten nie ?:

#!/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
źródło
5
na przykład, że „nie działa”, czyli styl csh dla pętli, brakuje nawiasów. for x ($d); do print $x; donezadziała i będzie pasować do pierwszej składni, którą wyliczyłeś na początku pytania.
Tim Kennedy,
1
To jest TAK szalone - że te dwa stwierdzenia - w rzeczywistości nie oba „działają tak samo”. Dosłownie nie mogę tego ogarnąć! Muszę zapalić trochę tego, co palili ci projektanci muszli ”, dawno temu, lol.
Alex Grey
Ostrożnie, w tej historii jest więcej niż się początkowo wydaje. Zapraszam do sprawdzenia mojej odpowiedzi.
jasonleonhard
Nie widziałem, żeby ktokolwiek o tym wspominał, ale obie formy pozwalają na pominięcie do / do: for i ({0..4..2}) for j ({a..c}) echo "($i,$j)"= {0,2,4}x{a,b,c}. Średniki dotyczą najbardziej zewnętrznej pętli, a przekierowania dotyczą najbardziej wewnętrznej, a jeśli chcesz to zmienić, potrzebujesz tylko nawiasów klamrowych: for i ({0..4..2}) { for j ({a..c}) echo "($i,$j)" } | cat -n= {1,...,9}*({0,2,4}x{a,b,c}). Oczywiście można łączyć pętle z rozszerzeniem zsh:for i ("("{0..4..2}","{a..c}")") echo $i
John P

Odpowiedzi:

58

Kilka form złożonych poleceń, takich jak pętle, ma alternatywne formy w zsh. Te formy są w większości inspirowane powłoką C , która była dość powszechna, gdy Zsh był młody, ale teraz zniknął. Te alternatywne formy działają dokładnie tak samo, jak zwykłe formy, to tylko inna składnia. Są nieco krótsze, ale mniej wyraźne.

Standardową formą forpolecenia jest for x in 1 2 3; do echo $x; done, a standardową formą whilepolecenia jest while test …; do somecommand; done. KSH atakujących i zsh mieć alternatywną postać for: for ((i = 0; i < 42; i++)); do somecommand; done, który naśladuje forpętle języków takich jak Pascal i C, w celu wyliczenia całkowitymi. Inne egzotyczne formy, które istnieją w zsh, są specyficzne dla zsh (ale często inspirowane przez csh).

Gilles „SO- przestań być zły”
źródło
Wielkie dzięki @Guilles. Nadal jestem trochę zdezorientowany. Która forma jest konkretna zsh? Dodałem też jeden przykład na końcu mojego OP, w którym nie mogę wymyślić, jak tłumaczyć między składniami. Jeśli różnica polega tylko na składni, jak powinienem naprawić drugi skrypt w dodatku, aby działał?
Amelio Vazquez-Reina
3
@intrpc Zobacz moją zaktualizowaną odpowiedź. Jeśli chodzi o twój ostatni przykład, to nie działa, ponieważ napisałeś for x $di zsh oczekuje albo, inalbo (gdzie napisałeś $d. Znaki interpunkcyjne i słowa zastrzeżone nie mogą pochodzić z rozszerzenia zmiennej, muszą zostać przeanalizowane, zanim powłoka będzie mogła rozpocząć się od rozszerzenia zmiennej.
Gilles „SO- przestań być zły”
@intrpc oba są specyficzne dla Zsh. zsh został specjalnie zaprojektowany do obsługi zarówno składni bourne, korn, jak i c-shell, ponieważ jest hybrydą wszystkich trzech.
Tim Kennedy,
1
@pseyfert Działa, ale nie ma żadnej przewagi nad formami, które pokazuję: jest mniej przenośny niż for (( … ))formularz i zużywa dużo pamięci, jeśli 3 jest duże.
Gilles „SO- przestań być zły”
1
@ alpha_989 W składni podobnej do sh potrzebujesz dopo ));. Zsh akceptuje także inną składnię, w for ((…)); COMMANDktórej COMMANDjest to jedno polecenie. Dlatego akceptuje for ((i = 1; i<100; i++)); ghi show $i | grep "log". Kiedy to zobaczy done, narzeka, bo nie było dokońca. Zobacz „Alternatywne formularze dla złożonych poleceń” w podręczniku .
Gilles „SO- przestań być zły”,