Intereting Posts

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

Я столкнулся с сценарием Zsh и хотел узнать его смысл. В приведенных ниже сценариях существует выражение ${$(@f)$(egrep "$2","$file")} . Из того, что я искал, @ должен использовать, представляют все позиционные параметры, но тогда postfix letter f не упоминается нигде в приведенном выше сценарии, и я не мог найти ни одного онлайн-материала, говорящего о его особом значении.

 #!/usr/bin/env zsh tmp_file="/tmp/_unsorted_find_n_grep" echo "--- find <$2> in <$1>" > $tmp_file find . -follow -iname "$1" | while read file do timestamp=$(ls -l --time-style=+"%Y-%m-%d %H:%M:%S" "$file" | gawk '{print $6, $7}') linestack=${(@f)$(egrep "$2" "$file")} for line in $linestack do echo "$timestamp $file: $line" >> $tmp_file done done cat $tmp_file | sort rm $tmp_file 

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

 ${(@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 

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

 @ In double quotes, array elements are put into separate words. Eg, '"${(@)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.