在 bash 中如何将 multimap<K,V> 转换为 <K, {V1,V2}> 的地图
In bash how to transform multimap<K,V> to a map of <K, {V1,V2}>
我正在处理 bash 中文件的输出,需要按键对值进行分组。
例如,我有
13,47099
13,54024
13,1
13,39956
13,0
17,126223
17,52782
17,4
17,62617
17,0
23,1022724
23,79958
23,80590
23,230
23,1
23,118224
23,0
23,1049
42,72470
42,80185
42,2
42,89199
42,0
54,70344
54,72824
54,1
54,62969
54,1
在一个文件中,并将来自特定键的所有值分组到一行中,如
13,47099,54024,1,39956,0
17,126223,52782,4,62617,0
23,1022724,79958,80590,230,1,118224,0,1049
42,72470,80185,2,89199,0
54,70344,72824,1,62969,1
我的输入文件中大约有 10000 个条目。如何在 shell 中转换此数据?
awk
救援!
假设键是连续的...
$ awk -F, 'p!= {if(a) print a; a=p=}
{a=a FS }
END {print a}' file
13,47099,54024,1,39956,0
17,126223,52782,4,62617,0
23,1022724,79958,80590,230,1,118224,0,1049
42,72470,80185,2,89199,0
54,70344,72824,1,62969,1
这是@karakfa 的代码对我们 awk
初学者所做的分解。我是根据玩具数据集 file
:
写的
1,X
1,Y
3,Z
p!=
: 检查模式 p!=
是否为 true
- 检查变量
p
是否等于 file
当前(第一)行的第一个字段(在本例中为 1
)
- 因为
p
此时未定义,它不能等于1
,所以p!=
是true
,我们继续这行代码
if(a) print a
:检查变量a
是否存在,如果存在则打印a
- 由于此时
a
未定义 print a
命令未执行
a=p=
:设置变量a
和p
等于当前(第一)行的第一个字段的值(在本例中为1
)
a=a FS
:设置变量a
等于a
加上当前(第一)行的第二个字段的值,由字段分隔符(1,X
在这种情况下)
END
:因为我们还没有到达file
的结尾,我们跳过这行代码的剩余部分
移动到 file
的下(第二)行并重新启动该行的 awk
代码
p!=
:检查模式p!=
是否为真
- 因为
p
是 1
并且当前(第二)行的第一个字段是 1
,p!=
是 false
我们跳过这行代码的其余部分
a=a FS
:设置a
等于a
的值和当前(第二)行的第二个字段的值,由字段分隔符(1,X,Y
在这种情况下)
END
:因为我们还没有到达file
的结尾,我们跳过这行代码的剩余部分
移动到file
的下(第三)行并重新启动awk
代码
p!=
: 检查模式 p!=
是否为 true
- 因为
p
是1
,第三行的</code>是<code>3
,p!=
是true
,我们继续这个代码行
if(a) print a
:检查变量a
是否存在,如果存在则打印a
- 因为此时
a
是 1,X,Y
,1,X,Y
被打印到输出
a=p=
:设置变量a
和p
等于当前(第三)行第一个字段的值(在本例中为3
)
a=a FS
:设置变量a
等于a
加上当前(第三)行的第二个字段的值,用字段分隔符(3,Z
在这种情况下)
END {print a}
:因为我们已经到了file
的末尾,所以执行这段代码
print a
:打印最后一组a
(本例中为3,Z
)
结果输出是
1,X,Y
3,Z
如果此描述中有任何错误,请告诉我。
对@karakfa 的回答进行微调。如果您希望键和值之间的分隔符与值之间的分隔符不同,可以使用此代码:
awk -F, 'p== {a=a "; " } p!= {if(a) print a; a=[=10=]; p=} END {print a}'
我正在处理 bash 中文件的输出,需要按键对值进行分组。
例如,我有
13,47099
13,54024
13,1
13,39956
13,0
17,126223
17,52782
17,4
17,62617
17,0
23,1022724
23,79958
23,80590
23,230
23,1
23,118224
23,0
23,1049
42,72470
42,80185
42,2
42,89199
42,0
54,70344
54,72824
54,1
54,62969
54,1
在一个文件中,并将来自特定键的所有值分组到一行中,如
13,47099,54024,1,39956,0
17,126223,52782,4,62617,0
23,1022724,79958,80590,230,1,118224,0,1049
42,72470,80185,2,89199,0
54,70344,72824,1,62969,1
我的输入文件中大约有 10000 个条目。如何在 shell 中转换此数据?
awk
救援!
假设键是连续的...
$ awk -F, 'p!= {if(a) print a; a=p=}
{a=a FS }
END {print a}' file
13,47099,54024,1,39956,0
17,126223,52782,4,62617,0
23,1022724,79958,80590,230,1,118224,0,1049
42,72470,80185,2,89199,0
54,70344,72824,1,62969,1
这是@karakfa 的代码对我们 awk
初学者所做的分解。我是根据玩具数据集 file
:
1,X
1,Y
3,Z
p!=
: 检查模式p!=
是否为true
- 检查变量
p
是否等于file
当前(第一)行的第一个字段(在本例中为1
) - 因为
p
此时未定义,它不能等于1
,所以p!=
是true
,我们继续这行代码
- 检查变量
if(a) print a
:检查变量a
是否存在,如果存在则打印a
- 由于此时
a
未定义print a
命令未执行
- 由于此时
a=p=
:设置变量a
和p
等于当前(第一)行的第一个字段的值(在本例中为1
)a=a FS
:设置变量a
等于a
加上当前(第一)行的第二个字段的值,由字段分隔符(1,X
在这种情况下)END
:因为我们还没有到达file
的结尾,我们跳过这行代码的剩余部分移动到
file
的下(第二)行并重新启动该行的awk
代码p!=
:检查模式p!=
是否为真- 因为
p
是1
并且当前(第二)行的第一个字段是1
,p!=
是false
我们跳过这行代码的其余部分
- 因为
a=a FS
:设置a
等于a
的值和当前(第二)行的第二个字段的值,由字段分隔符(1,X,Y
在这种情况下)END
:因为我们还没有到达file
的结尾,我们跳过这行代码的剩余部分移动到
file
的下(第三)行并重新启动awk
代码p!=
: 检查模式p!=
是否为true
- 因为
p
是1
,第三行的</code>是<code>3
,p!=
是true
,我们继续这个代码行
- 因为
if(a) print a
:检查变量a
是否存在,如果存在则打印a
- 因为此时
a
是1,X,Y
,1,X,Y
被打印到输出
- 因为此时
a=p=
:设置变量a
和p
等于当前(第三)行第一个字段的值(在本例中为3
)a=a FS
:设置变量a
等于a
加上当前(第三)行的第二个字段的值,用字段分隔符(3,Z
在这种情况下)END {print a}
:因为我们已经到了file
的末尾,所以执行这段代码print a
:打印最后一组a
(本例中为3,Z
)
结果输出是
1,X,Y
3,Z
如果此描述中有任何错误,请告诉我。
对@karakfa 的回答进行微调。如果您希望键和值之间的分隔符与值之间的分隔符不同,可以使用此代码:
awk -F, 'p== {a=a "; " } p!= {if(a) print a; a=[=10=]; p=} END {print a}'