像其他文件一样重新排序文件行(Unix)


2

是否有工具(或选项) sort )它将重新排序文件的行,以便它们像另一个文件中的键一样被排序?

例如,我有一个数据文件:

T01F01475558    30
T01F022B3A17    31
T01F022EEDFD    19
T01F026E0209    19

另一个(排序“关键”文件):

T01F022EEDFD
T01F026E0209
T01F022B3A17
T01F01475558

有没有办法对第一个文件进行排序,以便第一个字段与第二个文件的顺序相同?每个键都是唯一的(没有重复),每个文件中的行数相同。

是否有一个我不知道的UNIX工具会这样做?

Answers:


0

每个键都是唯一的(没有重复),每个文件中的行数相同。

这个假设是 非常 重要。如果它成立,那么这个命令将完成这项工作(在Bash中):

paste <(nl key.file | sort -k 2 | cut -f 1) <(sort data.file) | sort -n | cut -f 2-

很少有工具使用制表符作为分隔符。因此,不得出现制表符 key.file (它们可能发生在 data.file 虽然)。 Sane参赛作品 key.file 无论如何应该形成一个列,所以它应该不是问题。

说明:

  1. nl 在每一行的前面添加一个行号 key.file;这使得键本身移动到第二列; sort -k 2 根据第二列,即按键排序。然后丢弃密钥 cut -f 1
  2. 另一个 sort 排序 data.file。由于前面的键是唯一的,因此默认排序相当于根据唯一键进行排序。
  3. 这两个结果来自 sort -s被合并 paste。没有第一个 cut 示例行将是:

         4  T01F01475558    T01F01475558    30
    

    密钥的唯一性和两个文件中相同数量的密钥至关重要。实际上来自两者的相同键 sort -s在同一条线上相遇而离开 paste。因为你不需要重复的密钥来占用内存,所以第一个 cut 尽快使用。有了它真实的例子线离开 paste 更确切地说:

         4  T01F01475558    30
    
  4. 然后根据它们的数值对这些线进行分类。来自的行号 nl 在前面,所以这个操作引入了所需的顺序。

  5. 在末尾 cut 丢弃第一列,留下确切的行 data.file,但按照所需的顺序。

或者你可以尝试这个(在Bash中测试):

while IFS='' read -r ; do
   [ -n "$REPLY" ] && grep "^$REPLY " data.file
done <key.file

请注意,代码需要在每个键后面有一个空格字符 data.file

优点:

  • key.file 可以指定任意数量的键,重复键,不存在的键。在这种情况下,不要认为“排序”,认为“逐个检索所需的行”。
  • 您可以流输入(如stdin而不是 key.file,省略 <key.file )并在运行中获得输出。

缺点:

  • grep 将密钥解释为正则表达式,这可能适得其反。有 grep -F 但一般来说你需要 ^ 在模式中。
  • read 是慢的;产卵 grep 一次又一次缓慢;开盘 data.file 一次又一次很慢。
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.