I ran into a Zsh script and wanted to know its meaning. In the scripts below there is ${$(@f)$(egrep "$2","$file")}
expression. From what I searched, @
is to use represent all positional parameters, but then the postfix letter f
is not mentioned anywhere in above script and I couldn't find any online material saying its special meaning.
#!/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
Best Answer
The character inside the parentheses are parameter expansion flags. They can be used around a variable substitution or a command substitution, e.g.
The flag
f
splits the result of the expansion at newlines. The flag@
ensures that the resulting array is expanded as multiple words; oddly, it only has effect inside double quotes, where it acts as a generalization of"$@"
.Usually, these flags are used like this:
This way
lines
becomes an array where each element is one line of output fromegrep
.Here, the expansion is not in a context that allows multiple words, so the
@
flag has no effect. The effect of thef
flag is somewhat unintuitive: it forces an array context, so the IFS-separated words in theegrep
output are stored in a temporary array which is then joined with the first character ofIFS
.Contrast: