输入
119764469|14100733//1,k1=v1,k2=v2,STREET:1:1=NY
119764469|14100733//1,k1=v1,k2=v2,k3=v3
119764469|14100733//1,k1=v1,k4=v4,abc.xyz:1:1=nmb,abc,po.foo:1:1=yu
k1可以是任何带有字母数字的名称。 &:特殊字符,例如abc.nm.1:1
期望的输出(所有唯一的列),不需要/不必要的排序,应该是超快的
k1,k2,STREET:1:1,k3,k4,abc.xyz:1:1
我当前的方法/解决方案是
awk -F',' '{for (i=0; i<=NR; i++) {for(j=1; j<=NF; j++){split($j,a,"="); print a[1];}}}' file.txt | awk '!x[$1]++' | grep -v '|' | sed -e :a -e '$!N; s/\n/ | /; ta'
它可以正常工作,但对于文件太大(可能以MB或GB为单位)来说太慢了
注意:这在数据迁移中是必需的,应使用基本的unix shell命令,因为生产可能不允许使用第三方工具。
答案 0 :(得分:2)
不确定速度,请尝试一下
$ cut -d, -f2- file | # select the key/value pairs
tr ',' '\n' | # split each k=v to its own line
cut -d= -f1 | # select only keys
sort -u | # filter uniques
paste -sd, # serialize back to single csv line
abc.xyz:1:1,k1,k2,k3,k4,STREET:1:1
我希望它比grep
更快,因为不涉及任何正则表达式。
答案 1 :(得分:1)
使用grep -o
仅复制所需的部分:
grep -o -e '[^=,]\+=[^,]\+' file.txt |awk -F'=' '{print $1}' |sort |uniq |tr '\n' ',' |sed 's/,$/\n/'
>>> abc.xyz:1:1,k1,k2,k3,k4,STREET:1:1
(这里需要{sort
,因为否则uniq
无效)
答案 2 :(得分:0)
如果您真的不需要全部输出:
$ awk -F'[,=]' '{for (i=2;i<=NF;i+=2) print $i}' file | sort -u
abc.xyz:1:1
k1
k2
k3
k4
STREET:1:1
如果您这样做:
$ awk -F'[,=]' '{for (i=2;i<=NF;i+=2) print $i}' file | sort -u |
awk -v ORS= '{print sep $0; sep=","} END{print RS}'
abc.xyz:1:1,k1,k2,k3,k4,STREET:1:1
您可以在一个awk脚本中完成所有操作,但是我不确定它是否会像上面那样高效,或者如果/当数组增长到数百万个值时,可能会遇到内存问题:
$ cat tst.awk
BEGIN { FS="[,=]"; ORS="" }
{
for (i=2; i<=NF; i+=2) {
vals[$i]
}
}
END {
for (val in vals) {
print sep val
sep = ","
}
print RS
}
$ awk -f tst.awk file
k1,abc.xyz:1:1,k2,k3,k4,STREET:1:1