重新排列BASH中的列表

时间:2013-02-01 21:29:04

标签: bash awk

我有一个类似的文件:

FILE.DAT

1 2
1 3
2 1
2 4
2 3
3 4

左列已排序。我想写一个新文件谎言:

1 2 3
2 1 4 3
3 4

在第一列中,应该是file.dat的左列号,并且在它旁边是右列号。有什么帮助吗?

5 个答案:

答案 0 :(得分:3)

#!/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

答案 1 :(得分:3)

这些答案不要求将整个文件存储在内存中。它们都要求对文件进行排序。

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

答案 2 :(得分:2)

你已经接受了答案。但是我想为你有趣的问题添加另一个更简单(可能)的短单线。

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

答案 3 :(得分:2)

这也有效

awk '{a[$1]=a[$1]$2" "} END {for (i in a) {print i,a[i]}}' temp.txt

答案 4 :(得分:0)

这是使用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