zsh для итерации, как в bash

#bash #zsh

#bash #zsh

Вопрос:

Недавно я переключился с bash на zsh и не уверен, как этого добиться:

bash:

 $ list='aaa
> bbb
> ccc
> ddd'

$ for i in $list; do echo $i-xxx; done
aaa-xxx
bbb-xxx
ccc-xxx
ddd-xxx
  

в zsh я получаю:

 % list='aaa
quote> bbb
quote> ccc
quote> ddd'

% for i in $list; do echo $i-xxx; done
aaa
bbb
ccc
ddd-xxx
  

как заставить zsh делать это так же, как bash?

Комментарии:

1. Вы должны использовать массивы в обеих оболочках вместо того, что вы пытаетесь.

2. Проблема в том, что zsh по умолчанию не выполняется разделение слов при расширении параметра без кавычек. Существует опция, которую вы можете настроить, чтобы заставить ее делать это, но использование строки таким образом также не рекомендуется bash .

Ответ №1:

Скорее всего, рассмотрите возможность использования массива вместо:

 arraylist=(aaa bbb ccc ddd)
for i in "${arraylist[@]}"; do echo "$i-xxx"; done
  

Кажется, вы хотите выполнить итерацию по строкам в переменной, поэтому вы хотите сделать:

 while IFS= read -r i; do echo "$i-xxx"; done <<<"$list"
  

Если вы хотите добавить к каждой строке строку, используйте вместо -xxx sed :

 sed 's/$/-xxx/' <<<"$line"
  

Также есть xargs :

 xargs -d'n' -i echo {}-xxx <<<"$line"
  

Если вы хотите перебирать слова в строке, а слова могут быть в двойных кавычках, я бы выбрал xargs :

 xargs -i echo {}-xxx <<<"$line"
  

Если вы хотите перебирать слова в строке без интерпретации кавычек, способ в другом ответе с for i in $(echo $list) помощью совместим как с zsh, так и с bash

Комментарии:

1. это эхо — это только пример, я бы хотел выполнять разные действия для каждой строки в цикле итерации для каждой строки.. это может быть curl, nc или любая другая команда, где строка будет параметром..

Ответ №2:

Вы можете использовать флаг расширения параметра, чтобы разделить строку на новые строки:

 for line in ${(f)list}; do ...
  

Смотрите http://zsh.sourceforge.net/Doc/Release/Expansion.html#Parameter-Expansion-Flags

Комментарии:

1. Вы также можете использовать $=list для разделения строки, используя символы, из $IFS которых включает в себя новые строки. Это ближе к поведению bash. setopt shwordsplit также выполнит эту работу.

Ответ №3:

Вы должны разделить свою строку list на пробелы:

 for i in ${(z)list}
do
   echo $i
done
  

Конечно, вопрос в том, почему вы list в первую очередь определили как скаляр. Даже в bash, возможно, было бы разумнее использовать его как массив. В Zsh массив был бы (возможно — зависит от того, что еще вы хотите с ним сделать) даже более удобным, чем одна строка.