awk:将输出传递给关联数组
awk: passing output to associative array
是否可以将 awk 输出传递给关联数组?
例如,我有一个 test.csv 文件:
bill|gates|123
steve|jobs|234
elon|musk|345
如果我这样做:
awk 'BEGIN {FS="|"} {print ,,}' test.csv
我得到:
bill gates 123
steve jobs 234
elon musk 345
我能否在关联数组 (zsh
) 中获取结果而不是此输出,如下所示?
typeset -A foo=(
[bill gates]=123
[steve jobs]=234
[elon musk]=345
)
您可以使用此 awk
生成此输出,然后您可以 eval
在 zsh
中使用此输出来创建您的关联数组:
awk -F '|' 'BEGIN {print "typeset -A foo=("}
{print " [" , "]=" } END {print ")"}' file.csv
typeset -A foo=(
[bill gates]=123
[steve jobs]=234
[elon musk]=345
)
您能否解析 awk
中的数据并将 shell 的 (awk) 结果 re-parsed 存储在数组中?当然可以,但是为什么不减少开销而让 shell 直接解析文件并存储在数组中呢?
declare -A foo=()
while IFS='|' read -r fname lname val
do
ndx="${fname} ${lname}"
foo[${ndx}]="${val}"
done < test.csv
这会生成:
$ typeset -p foo
typeset -A foo=( ['bill gates']=123 ['elon musk']=345 ['steve jobs']=234 )
一种可能:
typeset -a lines=("${(f)$(awk 'BEGIN {FS="|"} {print ,,}' test.csv)}")
typeset -a keys=("${(@)lines% *}")
typeset -a vals=("${(@)lines##* }")
typeset -A ary=(${keys:^vals})
部分作品:
${(f)...}
- 在换行符处拆分 awk
的输出。
${...% *}
- 删除从最后一个 space 到最后的所有内容,留下前两个字段作为密钥。对于 (@)
和 double-quotes,这将应用于 lines
数组中的每个元素。
${...##* }
- 删除直到最后一个 space 的所有内容,保留值。
${...:^...}
- 将两个数组压缩在一起,所以我们最终得到 key1 val1 key2 val2 ...
.
typeset -A ...
- 使用 k1 v1 k2 v2 ...
语法创建关联数组。
另一个版本,仅使用zsh
:
typeset -a lines=("${(f)$(<test.csv)}")
typeset -a keys=("${(@)"${(@)lines%|*}"//|/ }")
typeset -a vals=("${(@)lines##*|}")
typeset -A ary=(${keys:^vals})
此变体和下面的变体可以处理值中的 spaces,例如.csv 文件中的 j k|rowling|44 192 411
将创建元素 ['j k rowling']='44 192 411'
.
通过对 awk
脚本进行一些更改,可以在一行中完成:
typeset -A ary=("${(@s:|:)${(f)"$(awk -F'|' '{print ,"|"}' test.csv)"}}")
是否可以将 awk 输出传递给关联数组?
例如,我有一个 test.csv 文件:
bill|gates|123
steve|jobs|234
elon|musk|345
如果我这样做:
awk 'BEGIN {FS="|"} {print ,,}' test.csv
我得到:
bill gates 123
steve jobs 234
elon musk 345
我能否在关联数组 (zsh
) 中获取结果而不是此输出,如下所示?
typeset -A foo=(
[bill gates]=123
[steve jobs]=234
[elon musk]=345
)
您可以使用此 awk
生成此输出,然后您可以 eval
在 zsh
中使用此输出来创建您的关联数组:
awk -F '|' 'BEGIN {print "typeset -A foo=("}
{print " [" , "]=" } END {print ")"}' file.csv
typeset -A foo=(
[bill gates]=123
[steve jobs]=234
[elon musk]=345
)
您能否解析 awk
中的数据并将 shell 的 (awk) 结果 re-parsed 存储在数组中?当然可以,但是为什么不减少开销而让 shell 直接解析文件并存储在数组中呢?
declare -A foo=()
while IFS='|' read -r fname lname val
do
ndx="${fname} ${lname}"
foo[${ndx}]="${val}"
done < test.csv
这会生成:
$ typeset -p foo
typeset -A foo=( ['bill gates']=123 ['elon musk']=345 ['steve jobs']=234 )
一种可能:
typeset -a lines=("${(f)$(awk 'BEGIN {FS="|"} {print ,,}' test.csv)}")
typeset -a keys=("${(@)lines% *}")
typeset -a vals=("${(@)lines##* }")
typeset -A ary=(${keys:^vals})
部分作品:
${(f)...}
- 在换行符处拆分awk
的输出。${...% *}
- 删除从最后一个 space 到最后的所有内容,留下前两个字段作为密钥。对于(@)
和 double-quotes,这将应用于lines
数组中的每个元素。${...##* }
- 删除直到最后一个 space 的所有内容,保留值。${...:^...}
- 将两个数组压缩在一起,所以我们最终得到key1 val1 key2 val2 ...
.typeset -A ...
- 使用k1 v1 k2 v2 ...
语法创建关联数组。
另一个版本,仅使用zsh
:
typeset -a lines=("${(f)$(<test.csv)}")
typeset -a keys=("${(@)"${(@)lines%|*}"//|/ }")
typeset -a vals=("${(@)lines##*|}")
typeset -A ary=(${keys:^vals})
此变体和下面的变体可以处理值中的 spaces,例如.csv 文件中的 j k|rowling|44 192 411
将创建元素 ['j k rowling']='44 192 411'
.
通过对 awk
脚本进行一些更改,可以在一行中完成:
typeset -A ary=("${(@s:|:)${(f)"$(awk -F'|' '{print ,"|"}' test.csv)"}}")