根据另一个文件中的列对文件进行排序

时间:2013-04-29 17:20:20

标签: linux shell sed awk

我有两个文件格式为:

loc1 num1 num2
loc2 num3 num4

第一列是位置,我想使用第一个文件中位置的顺序对第二个文件进行排序,这样我就可以将两个文件放在一起,其中数字适合该位置。

我可以编写一个perl脚本来执行此操作,但我觉得可能有一些快速/简单的shell / awk命令来实现此目的。你有什么想法吗?

感谢。

编辑:

这是输入,现在我实际上想要使用文件1中的第2列来排序file2。

File1中:

GID     location        NAME    GWEIGHT C1SI    M1CO    M1SI    C1LY    M1LY    C1CO    C1LI    M1LI
AID                             ARRY2X  ARRY1X  ARRY3X  ARRY4X  ARRY5X  ARRY0X  ARRY6X  ARRY7X
EWEIGHT                         1.000000        1.000000        1.000000        1.000000        1.000000        1.000000        1.000000        1.000000
GENE735X        chr17:66199278-66199496 chr17:66199278-66199496 1.000000        0.211785        -0.853890       1.071875        0.544136        0.703871     0.371880 0.218960        -2.268618
GENE1562X       chr10:80097054-80097298 chr10:80097054-80097298 1.000000        0.533673        -0.397202       0.783363        0.109824        -0.436342    0.158667 0.475748        -1.227730
GENE6579X       chr19:23694188-23694395 chr19:23694188-23694395 1.000000        0.127748        -0.203827       0.846738        0.045599        -0.211767    0.415442 0.282123        -1.302055

文件2:

GID     location        NAME    GWEIGHT C1SI    M1CO    M1SI    C1LY    M1LY    C1CO    C1LI    M1LI
AID                             ARRY2X  ARRY1X  ARRY3X  ARRY4X  ARRY5X  ARRY0X  ARRY6X  ARRY7X
EWEIGHT                         1.000000        1.000000        1.000000        1.000000        1.000000        1.000000        1.000000        1.000000
GENE6579X       chr19:23694188-23694395 chr19:23694188-23694395 1.000000        0.127748        -0.203827       0.846738        0.045599        -0.211767    0.415442 0.282123        -1.302055
GENE735X        chr17:66199278-66199496 chr17:66199278-66199496 1.000000        0.211785        -0.853890       1.071875        0.544136        0.703871     0.371880 0.218960        -2.268618
GENE1562X       chr10:80097054-80097298 chr10:80097054-80097298 1.000000        0.533673        -0.397202       0.783363        0.109824        -0.436342    0.158667 0.475748        -1.227730

2 个答案:

答案 0 :(得分:7)

awk解决方案:将第二个文件存储在内存中,然后遍历第一个文件,从第二个文件中发出匹配的行:

awk 'FNR==NR {x2[$1] = $0; next} $1 in x2 {print x2[$1]}' second first

实施@ Barmar的评论

join -1 2 -o "1.1 1.2 2.2 2.3" <(cat -n first | sort -k2) <(sort second) | 
sort -n | 
cut -d ' ' -f 2-

请注意其他回答者,我测试了这些文件:

$ cat first
foo x y
bar x y
baz x y
$ cat second
bar x1 y1
baz x2 y2
foo x3 y3

的解释
awk 'FNR==NR {x2[$1] = $0; next} $1 in x2 {print x2[$1]}' second first

此部分读取命令行参数中的第一个文件(此处为“second”):

FNR==NR {x2[$1] = $0; next}

条件FNR == NR仅对第一个命名文件为真。 FNR是awk的“文件记录号”变量,NR是来自所有输入源的当前记录号。当前行存储在一个名为x2的关联数组中(不是一个很好的变量名),该数组由记录的第一个字段索引。

下一个条件$1 in x2仅在完全读取文件“second”后才会启动。它将查看名为“first”的文件中第一行的字段,该操作将打印文件“second”中的相应行,该文件已存储在数组中。

请注意,awk命令中文件的顺序很重要。由于您根据名为“first”的文件控制输出,因此它必须是由awk处理的 last 文件。

答案 1 :(得分:0)

使用paste命令合并两个文件的行。 例如:

文件1:

f1_11   f1_12         
f1_21   f1_22         
f1_31   f1_32         
f1_41   f1_42     

file2的:

f2_11   f2_12         
f2_21   f2_22         
f2_31   f2_32         
f2_41   f2_42

➜~paste file1 file2

f1_11   f1_12           f2_11   f2_12         
f1_21   f1_22           f2_21   f2_22         
f1_31   f1_32           f2_31   f2_32         
f1_41   f1_42           f2_41   f2_42   

现在您可以对第1列进行排序。

paste file1 file2 | sort -k1,1

如果您不希望在最终输出中看到file1的数据,最后但并非最不重要的是剪切属于第二个文件的列:

paste file1 file2 | sort -k1,1 | cut -f4-6