订购一列然后在命令行中使用 awk 打印特定行

Order a column then print a certain row with awk in command line

我有一个这样的 txt 文件:

ID   row1   row2   row3   score
rs16 ...    ...    ...    0.23
rs52 ...    ...    ...    1.43
rs87 ...    ...    ...    0.45
rs89 ...    ...    ...    2.34
rs67 ...    ...    ...    1.89

Rows1-row3 无关紧要。

我有大约800万行,分数范围是0-3。我想要与成为前 1% 相关的分数。我在考虑按分数重新排序数据,然后打印 ~80,000 行?你们认为最好的代码是什么?

使用 GNU coreutils,您可以这样做:

sort -k5gr <(tail -n+2 infile) | head -n80KB

您可以像这样删除第 2 列到第 4 列来提高上述管道的速度:

tr -s ' ' < infile | cut -d' ' -f1,5 > outfile

或合计:

sort -k5gr <(tail -n+2 <(tr -s ' ' < infile | cut -d' ' -f1,5)) | head -n80KB

编辑

我注意到您只对结果的第 80000 行感兴趣,那么 sed -n 80000 {p;q} 而不是您建议的 head 才是正确的选择。

说明

尾巴:

  • -n+2 - 跳过 header.

排序:

  • k5 - 在第 5 列排序。
  • gr - 使排序选择反向的标志 general-numeric-sort。

头:

  • n - 要保留的行数。 KB 是一个 1000 的乘数,其他见 info head

使用 GNU awk,您可以通过将 PROCINFO["sorted_in"] 设置为 "@val_num_desc" 来对值进行排序。例如像这样:

parse.awk

# Set sorting method
BEGIN { PROCINFO["sorted_in"]="@val_num_desc" }

# Print header
NR == 1 { print ,  }

# Save 1st and 5th columns in g and h hashes respectively
NR>1 { g[NR] = ; h[NR] =  }

# Print values from g and h until ratio is reached
END {
  for(k in h) { 
    if(i++ >= int(0.5 + NR*ratio_to_keep)) 
      exit
    print g[k], h[k]
  }
}

运行 像这样:

awk -f parse.awk OFS='\t' ratio_to_keep=.01 infile