Каков эффект “$ {(@f) …}” в Zsh?

С zsh:

files=(*)
echo foo/bar/$^l

(${^array} включает расширение стиля расширения фигурной скобки для массива).

Или:

echo ./*(:s:.:foo/bar:)

Применяет замену стиля расширения истории к расширению имени файла.

С любой оболочкой

printf 'foo/bar/%s\n' *

Или:

set -- *
for i do
  set -- "$@" "foo/bar/$i"
  shift
done
echo "$@"

(отметьте это echo в большинстве оболочек выполняет некоторые преобразования на аргументах, которые это получает, так лучше избегается для произвольного входа).

6
27.01.2014, 23:21
2 ответа

Символ в круглых скобках является флагами расширения параметра. Они могут использоваться вокруг подстановки переменных или замены команды, например.

${(@f)SOME_VARIABLE}
${(@f)${(xyz)SOME_VARIABLE}}
${(@f)$(some-command)}

Флаг f разделяет результат расширения в новых строках. Флаг @ гарантирует, что полученный массив расширен как несколько слов; странно, это только имеет эффект в двойных кавычках, где это действует как обобщение "$@".

Обычно, эти флаги используются как это:

lines=("${(@f)$(egrep "$2" "$file")}")

Сюда lines становится массивом, откуда каждый элемент является одной строкой вывода egrep.

Здесь, расширение не находится в контексте, который позволяет несколько слов, таким образом, @ флаг не имеет никакого эффекта. Эффект f флаг несколько неинтуитивен: это вызывает контекст массива, таким образом, разделенные IFS слова в egrep вывод хранится во временном массиве, к которому затем присоединяются с первым символом IFS.

linestack=${(@f)$(egrep "$2" "$file")}

Контраст:

$ zsh -c 'a=${(f)$(echo hello world; echo wibble)}; print -lr $#a $a'
18
hello world wibble
$ zsh -c 'IFS=:$IFS; a=${(f)$(echo hello world; echo wibble)}; print -lr $#a $a'
18
hello:world:wibble
$ zsh -c 'IFS=:; a=${(f)$(echo hello world; echo wibble)}; print -lr $#a $a'
18
hello world
wibble

$ zsh -c 'a=(${(f)$(echo hello world; echo wibble)}); print -lr $#a $a' 
1
hello world wibble
$ zsh -c 'a=("${(@f)$(echo hello world; echo wibble)}"); print -lr $#a $a'
2
hello world
wibble
4
27.01.2020, 20:29

Согласно этой zsh документации

@    In double quotes, array elements are put into separate words. E.g., ‘"${(@)foo}"’
     is equivalent to ‘"${foo[@]}"’ and ‘"${(@)foo[1,2]}"’ is the same as ‘"$foo[1]"
     "$foo[2]"’. This is distinct from field splitting by the f, s or z flags, which still
     applies within each array element.
0
27.01.2020, 20:29

Теги

Похожие вопросы