我有2个CSV文件:a.txt包含数据,a_props.txt描述列的类型,例如:
A.TXT:
john,smith,jsmith@gmail.com,30,
peter,jones,27
a_props.txt:
name,surname,email,age
name,surname,age
如何根据从a_props.txt获取的索引从a.txt获取一种数据?
例如:年龄
30,27
或
30
27
答案 0 :(得分:3)
您可以使用paste
逐行合并这两个文件,并awk
检查您要查找的属性名称是否匹配:
paste -d, a_props.txt a.txt | awk -v PROP='age' -v FS=',' '{for (i=1; i<=NF/2; i++) if ($i == PROP) print $(NF/2+i)}'
在此示例中,输出为:
30
27
请注意,您只需更改PROP=<property>
即可获取其他列的值。
编辑:修正了PROP不是记录的最后一个字段的情况。
答案 1 :(得分:1)
使用进程替换和额外的FD来获取要读取的其他流,并并行读取道具和数据文件:
key=age
exec 9< <(tr , " " < a_props.txt) 10< <( tr , " " < a.txt )
while read -u 9 -a props ; do
read -u 10 -a data
for (( ix=0 ; $ix < ${#props[*]} ; ix++ )); do
if [ "${props[$ix]}" == $key ]; then
echo ${data[$ix]}
fi
done
done
流程替换是特定于bash的,并且不会在vanilla sh。
中工作另外,要非常小心一下&#34; csv&#34;文件是。一旦添加了引用字段等,它们就变得难以解析。在那时,我使用其他语言的现有csv包(例如,perl中的Text::CSV
或tcllib中的csv
包)
答案 2 :(得分:1)
这可能对您有用:
paste a_props.txt a.txt |
awk '{split($1,a,",");split($2,b,",");for(x in a){if(a[x]==v)print b[x]}}' v=age
答案 3 :(得分:0)
awk -F "," '{ a=1
while ((getline p < ARGV[2]) > 0) {
props[a]=
a++
}
close(ARGV[2])
}
ARGIND > 1 { exit }
{ for (elem in props) {
if (length(props[elem]) = NF) {
split(props[elem],header,",")
for (item in header) {
data[header[item]+=$i ","
}
}
}
END {
for (elem in data) {
split(gensub(",$","","g",data[elem]),d,",")
print elem ":"
for ( e in d ) {
print d[e]
}
}
}' a.txt a.props.txt
这可能有用,但我没有测试过。我不建议使用非常大的文件,因为脚本会将它们放入内存中。如果a_props.txt
包含两个或多个具有相同字段长度的行,例如:
name,age
name,email
此案例在上述脚本中处理 !并且脚本的参数顺序是 important 。