我有一个像这样的文件:
文件.dat
1 2
1 3
2 1
2 4
2 3
3 4
左列已排序。我想写一个新文件,如下所示:
1 2 3
2 1 4 3
3 4
第一列应该是 file.dat 的左列编号,旁边是右列编号。有什么帮助吗?
#!/bin/bash
awk -f <(cat - <<-'EOF'
{
b[$1, a[$1]++] = $2;
}
END {
for (i in a) {
printf "%d ", i;
for (j = 0; j < a[i]; j++) {
printf "%d ", b[i, j];
}
print ""
}
}
EOF
) < /dev/stdin
输出:
$ ./script.sh < file.dat
1 2 3
2 1 4 3
3 4
该脚本将与awk
. 名称如果file.awk
:
{
b[$1, a[$1]++] = $2;
}
END {
for (i in a) {
printf "%d ", i;
for (j = 0; j < a[i]; j++) {
printf "%d ", b[i, j];
}
print ""
}
}
像这样运行:
awk -f file.awk < file.dat
这些答案不需要将整个文件存储在内存中。它们都要求对文件进行排序。
awk:
awk '
$1 != prev {
if (NR > 1) print ""
printf "%d %d", $1, $2
prev=$1
next
}
{printf " %d", $2}
END {print ""}
' file.dat
等效的bash:
prev=""
while read a b; do
if [[ $prev != $a ]]; then
[[ -n $prev ]] && echo
printf "%d %d" $a $b
prev=$a
else
printf " %d" $b
fi
done < file.dat
echo
好吧,您已经接受了答案。但是,我想为您的有趣问题添加另一个更简单(也许)的简短单行。
awk '$1 in a{a[$1]=a[$1]" "$2;next}{a[$1]=$0}END{for(i in a)print a[i]}' file
看到它与您的示例一起使用:
kent$ cat test.txt
1 2
1 3
2 1
2 4
2 3
3 4
kent$ awk '$1 in a{a[$1]=a[$1]" "$2;next}{a[$1]=$0}END{for(i in a)print a[i]}' test.txt
1 2 3
2 1 4 3
3 4
这也有效
awk '{a[$1]=a[$1]$2" "} END {for (i in a) {print i,a[i]}}' temp.txt
这是一种使用方法awk
:
awk '{ a[$1] = (a[$1] ? a[$1] FS : "") $2 } END { for (i in a) print i, a[i] | "sort" }' file
结果:
1 2 3
2 1 4 3
3 4