Для петель в 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буде працювати, і він відповідатиме першому синтаксису, який ви перерахували на початку запитання.
Тім Кеннеді

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
Джон П

Відповіді:


58

Кілька форм складних команд, таких як петлі, мають альтернативні форми в zsh. Ці форми здебільшого надихаються оболонкою С , яка була досить поширеною, коли zsh був молодим, але зараз зник. Ці альтернативні форми діють точно так само, як і звичайні форми, вони просто інший синтаксис. Вони трохи коротші, але менш чіткі.

Стандартною формою для forкоманди є for x in 1 2 3; do echo $x; done, а стандартною формою для whileкоманди є while test …; do somecommand; done. Ksh, bash і zsh мають альтернативну форму for:, for ((i = 0; i < 42; i++)); do somecommand; doneяка імітує forпетлі мов, таких як Pascal або C, для перерахування цілих чисел. Інші екзотичні форми, які існують в zsh, характерні для zsh (але часто натхненні csh).


Дуже дякую @Guilles. Я все ще трохи розгублений. Яка форма є специфічною zsh? Крім того, я додав один приклад наприкінці своєї ОП, де я не можу зрозуміти, як перекласти між синтаксисами. Якщо різниця - це лише синтаксис, як я повинен виправити другий скрипт у додатку, щоб він працював?
Амеліо Васкес-Рейна

3
@intrpc Дивіться мою оновлену відповідь. Що стосується вашого останнього прикладу, він не працює, тому що ви писали for x $dі zsh очікує або того, inабо (там, де ви написали $d. Знаки пунктуації та зарезервовані слова не можуть походити від розширення змінної, їх потрібно проаналізувати, перш ніж оболонка може запуститися в розширення змінної.
Жил "ТАК - перестань бути злим"

@intrpc обидва zsh специфічні. zsh був розроблений спеціально для підтримки синтаксису bourne, korn та c-shell, оскільки це гібрид усіх трьох.
Тім Кеннеді,

1
@pseyfert Це працює, але він не має жодної переваги перед формами, які я показую: він менш портативний, ніж for (( … ))форма, і використовує багато пам'яті, якщо 3 великий.
Жил "ТАК - перестань бути злим"

1
@ alpha_989 У ш-подібному синтаксисі вам потрібно doпісля ));. Zsh також приймає інший синтаксис, for ((…)); COMMANDде COMMANDє одна команда. Ось чому це приймає for ((i = 1; i<100; i++)); ghi show $i | grep "log". Коли це бачить doneпісля цього, скаржиться, бо не було doкінця. Див. "Чергові форми для складних команд" в цьому посібнику .
Жил "ТАК - перестань бути злим"
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.