Zsh中"${(@f)...}"的作用是什么?

Nat*_*tal 6 zsh variable-substitution

我遇到了一个 Zsh 脚本,想知道它的含义。在下面的脚本中有${$(@f)$(egrep "$2","$file")}表达式。从我搜索到的,@是使用代表所有位置参数,但是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
Run Code Online (Sandbox Code Playgroud)

Gil*_*il' 7

括号内的字符是参数扩展标志。它们可以用于变量替换或命令替换,例如

${(@f)SOME_VARIABLE}
${(@f)${(xyz)SOME_VARIABLE}}
${(@f)$(some-command)}
Run Code Online (Sandbox Code Playgroud)

该标志f在换行符处分割扩展的结果。该标志@确保将结果数组扩展为多个字;奇怪的是,它只在双引号内有效,它充当"$@".

通常,这些标志的使用方式如下:

lines=("${(@f)$(egrep "$2" "$file")}")
Run Code Online (Sandbox Code Playgroud)

这种方式lines成为一个数组,其中每个元素都是 的一行输出egrep

这里,扩展不是在允许多个单词的上下文中,因此该@标志不起作用。该f标志的效果有些不直观:它强制使用数组上下文,因此输出中以 IFS 分隔的单词egrep存储在临时数组中,然后与 的第一个字符连接IFS

linestack=${(@f)$(egrep "$2" "$file")}
Run Code Online (Sandbox Code Playgroud)

对比:

$ 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
Run Code Online (Sandbox Code Playgroud)


Tim*_*tin 0

根据这个 zsh 文档

\n\n
@    In double quotes, array elements are put into separate words. E.g., \xe2\x80\x98"${(@)foo}"\xe2\x80\x99\n     is equivalent to \xe2\x80\x98"${foo[@]}"\xe2\x80\x99 and \xe2\x80\x98"${(@)foo[1,2]}"\xe2\x80\x99 is the same as \xe2\x80\x98"$foo[1]"\n     "$foo[2]"\xe2\x80\x99. This is distinct from field splitting by the f, s or z flags, which still\n     applies within each array element.\n
Run Code Online (Sandbox Code Playgroud)\n