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

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

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

例如我有一个数据文件:

T01F01475558    30
T01F022B3A17    31
T01F022EEDFD    19
T01F026E0209    19

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

T01F022EEDFD
T01F026E0209
T01F022B3A17
T01F01475558

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

是否存在我不知道的可以执行此操作的 UNIX 工具?

答案1

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

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

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

很少有工具使用制表符作为分隔符。因此制表符不能出现在 中key.file(尽管它们可以出现在 中data.file)。无论如何, 中的合理条目key.file应该形成单个列,所以这应该不是问题。

解释:

  1. nl在 的每一行前面添加一个行号key.file;这会使键本身移动到第二列;sort -k 2根据第二列(即键)进行排序。然后键被 丢弃cut -f 1
  2. sort一种排序方式是data.file,由于前面的键是唯一的,所以这种默认排序相当于按照唯一的键进行排序。
  3. -s的两个结果sort通过 合并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反复打开很慢。

相关内容