首页 > 解决方案 > 重新排列以相同字符串开头的行

问题描述

我正在尝试重新排列file1已按最后一列排序的内容,如下所示

MEL P 20190731 0453 30.599
PUS P 20190731 0453 30.612
MEA P 20190731 0453 30.620
KDT P 20190731 0453 30.639
PAS P 20190731 0453 30.644
BDT P 20190731 0453 30.900
LAB P 20190731 0453 31.046
KLS P 20190731 0453 31.129
MEL S 20190731 0453 31.222
KDT S 20190731 0453 31.249
PAS S 20190731 0453 31.255
MEA S 20190731 0453 31.258
GRA P 20190731 0453 31.263
BDT S 20190731 0453 31.551
LAB S 20190731 0453 31.630
GRA S 20190731 0453 31.816

我想要在output第一列中包含相同字符串的每一行沿线彼此相邻分组,例如

MEL P 20190731 0453 30.599
MEL S 20190731 0453 31.222
PUS P 20190731 0453 30.612
MEA P 20190731 0453 30.620
MEA S 20190731 0453 31.258
KDT P 20190731 0453 30.639
KDT S 20190731 0453 31.249
PAS P 20190731 0453 30.644
PAS S 20190731 0453 31.255
BDT P 20190731 0453 30.900
BDT S 20190731 0453 31.551
LAB P 20190731 0453 31.046
LAB S 20190731 0453 31.630
KLS P 20190731 0453 31.129
GRA P 20190731 0453 31.263
GRA S 20190731 0453 31.816

同时仍然尊重最后一列的顺序(请注意,例如MEL,现在彼此相邻,并且该PUS位置相对于其他位置没有改变)。

我已经尝试过这段代码来生成一个key

awk '!array[$1]++ {print $1}' file1 > key

然后我尝试将其与之匹配file1以便能够使用重新排序行

grep -Fwf key file > output

但没有任何改变。请帮忙!

标签: awkgrep

解决方案


在 awk 中:

$ awk '{
    if(!($1 in a))           # enumerate all unique $1 for looping in END
        n[++c]=$1
    a[$1]=a[$1] $0 ORS       # append records to hash keyed on $1
}
END {                        # after processing records
    for(i=1;i<=c;i++)        # loop 
        printf "%s",a[n[i]]  # and output
}' file

输出:

MEL P 20190731 0453 30.599
MEL S 20190731 0453 31.222
PUS P 20190731 0453 30.612
MEA P 20190731 0453 30.620
MEA S 20190731 0453 31.258
KDT P 20190731 0453 30.639
KDT S 20190731 0453 31.249
PAS P 20190731 0453 30.644
PAS S 20190731 0453 31.255
BDT P 20190731 0453 30.900
BDT S 20190731 0453 31.551
LAB P 20190731 0453 31.046
LAB S 20190731 0453 31.630
KLS P 20190731 0453 31.129
GRA P 20190731 0453 31.263
GRA S 20190731 0453 31.816

它期望数据在最后一个字段上排序。


推荐阅读