我有一个 txt 文件作为输入,其中有 3 列,除以“,”(ID、info1 和 info2)。我想获得一个输出,其中存在基于 ID 的所有可能的唯一匹配对。对于每个匹配对,所有相关信息都应该关联起来。
输入.txt
Id,info1,info2
6,7.2,79.16
7,6.6,78.93
8,6.1,78.06
输出.txt
ID1,ID2,info1.1,info1.2,info2.1,info2.2
6,7,7.2,6.6,79.16,78.93
6,8,7.2,6.1,79.16,78.06
7,8,6.6,6.1,78.93,78.06
我怎样才能做到这一点?有人可以帮我吗?
答案1
一些 Perl,与列表::更多实用工具来自 CPAN:
perl -MList::MoreUtils=zip -F, -lne '
next if $. == 1;
push @lines, [@F];
} END {
print "id1,id2,info1.1,info1.2,info2.1,info2.2";
for ($i = 0; $i < @lines - 1; $i++) {
for ($j = $i+1; $j < @lines; $j++) {
print join ",", zip @{$lines[$i]}, @{$lines[$j]};
}
}
' input.txt
答案2
csvsql
您也许可以使用from将其作为数据库表自连接来完成csvkit:
csvsql --no-inference --query '
SELECT a.Id AS ID1, b.Id AS ID2, a.info1 AS [info1.1], b.info1 AS [info1.2], a.info2 AS [info2.1], b.info2 AS [info2.2]
FROM input a JOIN input b ON a.Id < b.Id
' input.txt
ID1,ID2,info1.1,info1.2,info2.1,info2.2
6,7,7.2,6.6,79.16,78.93
6,8,7.2,6.1,79.16,78.06
7,8,6.6,6.1,78.93,78.06
答案3
在每个 Unix 机器上的任何 shell 中使用任何 awk:
$ cat tst.awk
BEGIN { FS=OFS="," }
{ map[NR] = $0 }
END {
n = split(map[1],a)
printf "%s%s%s%s", "ID1", OFS, "ID2", (k<n ? OFS : ORS)
for ( k=2; k<=n; k++ ) {
printf "%s.1%s%s.2%s", a[k], OFS, a[k], (k<n ? OFS : ORS)
}
for ( i=2; i<=NR; i++ ) {
split(map[i],a)
for ( j=i+1; j<=NR; j++ ) {
split(map[j],b)
for ( k=1; k<=n; k++ ) {
printf "%s%s%s%s", a[k], OFS, b[k], (k<n ? OFS : ORS)
}
}
}
}
$ awk -f tst.awk input.txt
ID1,ID2,info1.1,info1.2,info2.1,info2.2
6,7,7.2,6.6,79.16,78.93
6,8,7.2,6.1,79.16,78.06
7,8,6.6,6.1,78.93,78.06