我想根据制表符分隔文件的第1列中的值获得某些列(2,4,5)中所有值的逗号分隔列表。
我正在调整下面的命令,但相反,它会给我列中所有值的列表,而不仅仅是每个人的值-我不确定如何做到这一点。
awk -F"t" '{print $2}' $i | sed -z 's/n/,/g;s/,$/n/'
这是我正在处理的
Bob 24 M apples red
Bob 12 M apples green
Linda 56 F apples red
Linda 102 F bananas yellow
这就是我想要得到的(我想保留重复项和顺序)
Bob 24,12 M apples,apples red,green
Linda 56,102 F apples,bananas red,yellow
假设:
- 对于重复的名称,性别将始终相同,否则保存'最后一次看到的'
Oneawk
idea:
awk '
BEGIN { FS=OFS="t" }
{ nums[$1] = nums[$1] sep[$1] $2
gender[$1] = $3
fruits[$1] = fruits[$1] sep[$1] $4
colors[$1] = colors[$1] sep[$1] $5
sep[$1] = ","
}
END { # PROCINFO["sorted_in"]="@ind_str_asc" # this line requires GNU awk
for (name in nums)
print name,nums[name],gender[name],fruits[name],colors[name]
}
' input.tsv
由此产生:
Bob 24,12 M apples,apples red,green
Linda 56,102 F apples,bananas red,yellow
注意:这恰好按照名称顺序显示输出;如果需要保证排序(按名称),OP可以通过sort
运行输出,或者如果使用GNU awk
,则取消PROCINFO["sorted_in"]
行
当您使用awk时,您永远不需要sed。
假设您的关键值(第一个字段)按示例中所示分组(如果不是,则先对文件进行排序),那么无需将整个文件读取到内存中,并且对于任何数量的输入字段(您只需确定哪些字段编号不累积值,即在这种情况下字段1和3),您可以这样做:
$ cat tst.awk
BEGIN { FS=OFS="t" }
$1 != vals[1] {
if ( NR>1 ) {
prt()
}
delete vals
}
{
for ( i=1; i<=NF; i++ ) {
pre = ( (i in vals) && (i !~ /^[13]$/) ? vals[i] "," : "" )
vals[i] = pre $i
}
}
END { prt() }
function prt( i) {
for ( i=1; i<=NF; i++ ) {
printf "%s%s", vals[i], (i<NF ? OFS : ORS)
}
}
$ awk -f tst.awk file
Bob 24,12 M apples,apples red,green
Linda 56,102 F apples,bananas red,yellow