提前致谢!
我有一个包含 3 列的文件,如下所示:
serv1 red group1
serv1 black group1
serv1 orange group1
serv1 red group2
serv1 orange group2
serv1 red group3
serv1 black group3
serv1 orange group3
serv2 orange group1
serv2 red group2
serv2 orange group2
serv2 red group3
serv2 black group3
serv2 orange group3
serv3 orange group1
serv3 red group1
我会这样展示:
serv1 group1 red black orange
serv1 group2 red orange
serv1 group3 red black orange
serv2 group1 orange
serv2 group2 red orange
serv2 group3 red black orange
serv3 group1 orange red
如果我尝试仅按第一个与下一个代码进行分组,我会表现得很好,但我无法对多个代码进行分组:
awk '{ V_GRUPO[$1]= (V_GRUPO[$1]==""?"":V_GRUPO[$1] OFS) $2 }END { for(x in V_GRUPO) print x, V_GRUPO[x] }' file.txt
serv1 red black orange red orange red black orange
serv2 orange red orange red black orange
serv3 orange red
¿我怎么能做到呢???
谢谢!!
答案1
假设输入中的字段由多个空格分隔(一种“漂亮打印的表格”格式),并且您希望根据其他两个字段将第二个字段中的条目折叠到以空格分隔的列表中:
$ mlr --pprint -N nest --ivar ' ' -f 2 then reorder -f 1,3,2 file
serv1 group1 red black orange
serv1 group2 red orange
serv1 group3 red black orange
serv2 group1 orange
serv2 group2 red orange
serv2 group3 red black orange
serv3 group1 orange red
这会使用以下命令对原始字段进行折叠和重新排序磨坊主( mlr
)。
如果数据是制表符分隔 (TSV),并且您想要制表符分隔输出,则更--pprint
改为--tsv
.您是否想要为折叠的数据列表使用不同的分隔符,然后更改--ivar ' '
为例如--ivar ';'
(以使用;
)。
例如,对于制表符分隔的输入和输出,使用;
作为列表分隔符:
$ mlr --tsv -N nest --ivar ';' -f 2 then reorder -f 1,3,2 file
serv1 group1 red;black;orange
serv1 group2 red;orange
serv1 group3 red;black;orange
serv2 group1 orange
serv2 group2 red;orange
serv2 group3 red;black;orange
serv3 group1 orange;red
另一个例子,读取 TSV 输入,向每个字段添加标签,使用这些标签而不是数字字段,并生成打印精美的表格输出:
$ mlr --itsv --implicit-csv-header --opprint --barred label Server,Colour,Group then nest --ivar ';' -f Colour then reorder -f Server,Group,Colour file
+--------+--------+------------------+
| Server | Group | Colour |
+--------+--------+------------------+
| serv1 | group1 | red;black;orange |
| serv1 | group2 | red;orange |
| serv1 | group3 | red;black;orange |
| serv2 | group1 | orange |
| serv2 | group2 | red;orange |
| serv2 | group3 | red;black;orange |
| serv3 | group1 | orange;red |
+--------+--------+------------------+
答案2
使用awk脚本,脚本文件.awk :
{
k = $1 OFS $3
a[k] = (k in a ? a[k] OFS : "" ) $2
}
END{
for(key in a){
print key, a[key]
}
}
然后运行:
awk -f script-file.awk input
a[k]
是一个使用键的数组k = $1 OFS $3
OFS
是输出字段分隔符?
是一个条件式 (test ? true : false
)for(key in a)
对于每个键
这可能不会被排序,所以如果你需要它排序管道它:
awk -f script-file.awk input | sort
答案3
由于您的输入已按 2 个键字段排序,因此使用任何 awk 时,一次只会在内存中保存 1 个键对的值:
$ awk '
{ key = $1 OFS $3 }
key != prev { if (NR>1) print vals; prev=vals=key }
{ vals = vals OFS $2 }
END { print vals }
' file
serv1 group1 red black orange
serv1 group2 red orange
serv1 group3 red black orange
serv2 group1 orange
serv2 group2 red orange
serv2 group3 red black orange
serv3 group1 orange red
如果您的实际输入尚未按照示例输入进行排序,则只需先对其进行排序:
sort -b -k1,1 -k3,3 file | awk '...'
答案4
datamash
要折叠一个列组,可以使用另一个列(或其他列) 。
$ datamash -sW groupby 1,3 collapse 2 --collapse-delimiter ' ' <file
关于折叠分隔符的手册:
--collapse-delimiter=x
-c x
Use character X instead of comma to delimit items in a ‘collapse’ or ‘unique’ (aka ‘uniq’) list.