Я хотел бы создать экземпляр массива zsh из подоболочки
myarray=($(somecommand)
и я проверяю, получил ли я то, что хотел
for element in $myarray ; do echo "===" ; echo $element ; echo "---" ; done
По умолчанию я вижу, что пробелы (пробелы и разрывы строк) используются для разделения элементов.
Я также обнаружил, что могу использовать ${(s:-:)"$(somecommand)"}
для разделения на -
, в этом случае пробелы и разрывы строк не разбивают элементы (т.е. элементы массива могут содержать разрывы строк).
Пока что я не могу разбить только на разрывы строк. Т.е. если somecommand
какая-то somecommand
Alice Bob Arthur C Clarke Neo Thomas Anderson
Я хочу, чтобы мой цикл for
печатал:
=== Alice --- === Bob --- === Arthur C Clarke --- === Neo --- === Thomas Anderson ---
Как мне этого добиться? (И, возможно, указатели, где искать это в руководстве.)
Собственный оператор расщепления (кроме расщепления слов по $IFS
подобного Борну, который выполняется при подстановках команд без кавычек) с флагом расширения параметра s
:
array=(${(ps:\n:)"$(cmd)"})
будет разделять вывод команды cmd
на новую строку, отбрасывая пустые элементы (пустые строки).
p
– включить эти \x
расширения. Поскольку ps:\n:
является распространенным, он имеет более короткий псевдоним: f
(для разделения на строки):
array=(${(f)"$(cmd)"})
Чтобы сохранить пустые строки, вы должны сделать:
array=("${(f@)$(cmd)"})
Теперь имейте в виду, что, как и в большинстве других оболочек, подстановка команд удаляет все завершающие символы новой строки, поэтому все завершающие пустые строки. Чтобы сохранить их, вы можете сделать:
array=("${(f@)$(cmd; echo .)}") array[-1]=() # remove that last line added by echo .
С разделением слов $IFS
:
IFS=$'\n' array=($(cmd)) # removes empty lines. Note that contrary to other # Bourne-like shells, zsh doesn't to globbing there # so you don't need the "set -o noglob" IFS=$'\n\n' # like in ksh93, doubling an IFS-whitespace character # removes its special treatment as a whitespace character array=($(cmd)) # preserves empty lines except the trailing ones IFS=$'\n\n' array=($(cmd; echo .)); array[-1]=() # preserves all empty lines.
Чтобы избежать глобального изменения $IFS
, вы можете сделать это в анонимной функции:
(){ local IFS=$'\n\n' array=($(cmd; echo .)); array[-1]=() }
Также помните, что расширение $array
пропускает пустые элементы. Поэтому, если вы хотите перебрать все элементы, включая пустые, вам понадобится:
for i ("$array[@]") ...
или же
for i ("${(@)array}") ...
не
for i ($array) ... for i in $array