我的数据看起来像这样:
i,a,b,c
1,0.2,3.2,4.5
2,0.8,4.1,3.5
3,0.5,3.1,4.1
i,a,b,c,d
4,3.2,5.2,7.5,1.1
5,2.8,5.1,8.5,0.9
6,2.5,5.1,8.1,1.0
i,a,d
7,3.2,5.2
8,2.8,5.1
9,2.5,5.1
我想用TXR处理它,看起来像这样:
i,key,val
1,a,0.2
1,b,3.2
1,c,4.5
2,a,0.8
2,b,4.1
2,c,3.5
3,a,0.5
3,b,3.1
3,c,4.1
4,a,3.2
4,b,5.2
4,c,7.1
4,d,1.1
5,a,2.8
5,b,5.1
5,c,8.5
5,d,0.9
6,a,2.5
6,b,5.1
6,c,8.1
6,d,1.0
7,a,3.2
7,b,5.2
8,a,2.8
8,b,5.1
9,a,2.5
9,b,5.1
我目前不正确的TXR脚本是:
@(output)
i,key,val
@(end)
@(repeat)
i,@(coll)@{key /[^,]+/}@(end)
@ (collect :gap 0)
@{i /[0-9]+/},@(coll)@{value /[^,]+/}@(end)
@ (end)
@ (output)
@ (repeat)
@ (repeat)
@i,@key,@value
@ (end)
@ (end)
@ (end)
@(end)
它代之以:
i,key,val
1,a,0.2
1,a,3.2
1,a,4.5
2,b,0.8
2,b,4.1
2,b,3.5
3,c,0.5
3,c,3.1
3,c,4.1
4,a,3.2
4,a,5.2
4,a,7.5
4,a,1.1
5,b,2.8
5,b,5.1
5,b,8.5
5,b,0.9
6,c,2.5
6,c,5.1
6,c,8.1
6,c,1.0
7,a,3.2
7,a,5.2
8,d,2.8
8,d,5.1
9,,2.5
9,,5.1
如何实现所需的输出?我可以以某种方式使用@(merge)
,还是需要下载到lisp?我看到有一个transpose
函数可能对此有用。
答案 0 :(得分:1)
代码几乎就在那里。问题是值必须与键相关联。为此,我们可以利用2016年6月29日发布的TXR 144中添加的功能::counter
和collect
支持的coll
关键字:
@(output)
i,key,val
@(end)
@(repeat)
i,@(coll)@{keylist /[^,]+/}@(end)
@ (collect :gap 0)
@{i /[0-9]+/},@(coll :counter c)@{value /[^,]+/}@(bind key @[keylist c])@(end)
@ (end)
@ (output)
@ (repeat)
@ (repeat)
@i,@key,@value
@ (end)
@ (end)
@ (end)
@(end)
密钥被收集到keylist
变量中而不是key
中,而key
与value
绑定在一起,通过keylist
索引c
}}。计数器c
默认为0;可以使用:counter (c expr)
指定不同的起始值。
但是,不要以这种笨重的方式做到这一点。我的意思是,看看我们在做什么:我们反复通过keys
踩到这个计数器,只是收集与值并行的键列表。我们可以使用内部bind
之外的单个coll
来实现完全相同的内容,如下所示:
@(output)
i,key,val
@(end)
@(repeat)
i,@(coll)@{keylist /[^,]+/}@(end)
@ (collect :gap 0)
@{i /[0-9]+/},@(coll)@{value /[^,]+/}@(end)
@ (bind key keylist)
@ (end)
@ (output)
@ (repeat)
@ (repeat)
@i,@key,@value
@ (end)
@ (end)
@ (end)
@(end)
请参阅?要获取每行的value
列表,我们会收集值。密钥不会因行而异,因此要获取每个key
列表以与value
配对,我们只需将其与keylist
绑定。
如果我们想要用这个逻辑来获取打印输出,那么我们就不能在每一行之后收集行和输出。换句话说,它只是收集关键名称的练习,然后将它们与给定部分中每行的值一起转储:
@(output)
i,key,val
@(end)
@(repeat)
i,@(coll)@{key /[^,]+/}@(end)
@ (repeat :gap 0)
@{i /[0-9]+/},@(coll)@{value /[^,]+/}@(end)
@ (output)
@ (repeat)
@i,@key,@value
@ (end)
@ (end)
@ (end)
@(end)
可以说,对于Awk来说这是一项很好的任务。不一定是Unix,请注意:
(awk (:set fs "," ofs ",")
(:let keys)
(:begin (prn 'i 'key 'val))
((equal [f 0] "i") (set keys (rest f))
(next))
(f (each ((k keys)
(v (rest f)))
(prn [f 0] k v))))