最近,我不得不根据记录的ID对几个文件进行排序;问题是可以有几种类型的记录,在每种类型中,我必须用于排序的字段都位于不同的位置.然而,由于key=value struct ,这些字段很容易识别.要显示一般 struct 的简单示例,请执行以下操作:

fieldA=valueA|fieldB=valueB|recordType=A|id=2|fieldC=valueC
fieldD=valueD|recordType=B|id=1|fieldE=valueE
fieldF=valueF|fieldG=valueG|fieldH=valueH|recordType=C|id=3

我提出了一个管道,如下所示,它完成了这项工作:

awk -F'[|=]' '{for(i=1; i<=NF; i++) {if($i ~ "id") {i++; print $i"?"$0} }}' tester.txt | sort -n | awk -F'?' '{print $2}'

换言之,算法如下:

  1. 通过字段和键值分隔符(|=)拆分记录
  2. 遍历元素并搜索id
  3. 打印下一个元素(id键的值)、分隔符和整行
  4. 按数字排序
  5. 删除前置标识符以保留记录的 struct

处理样本会得到以下输出:

fieldD=valueD|recordType=B|id=1|fieldE=valueE
fieldA=valueA|fieldB=valueB|recordType=A|id=2|fieldC=valueC
fieldF=valueF|fieldG=valueG|fieldH=valueH|recordType=C|id=3

但是,有没有一种方法可以使用单个awk命令来完成此任务?

推荐答案

您可以在一个命令中try 此gnu-awk代码:

awk -F'|' '{
   for(i=1; i<=NF; ++i)
      if ($i ~ /^id=/) {
         a[gensub(/^id=/, "", 1, $i)] = $0
         break
      }
}
END {
   PROCINFO["sorted_in"] = "@ind_num_asc"
   for (i in a)
      print a[i]
}' file

fieldD=valueD|recordType=B|id=1|fieldE=valueE
fieldA=valueA|fieldB=valueB|recordType=A|id=2|fieldC=valueC
fieldF=valueF|fieldG=valueG|fieldH=valueH|recordType=C|id=3

我们使用|作为字段分隔符,当有一个以id=开头的列名时,我们将其存储在数组a中,索引作为=后面的文本,值作为完整记录.

使用PROCINFO["sorted_in"] = "@ind_num_asc",我们使用索引的数值对数组a进行排序,然后在for循环中打印值部分以获得排序后的输出.

Linux相关问答推荐

AWK+向AWK导出值未传递

如何告诉链接器不要在链接的共享库中查找某些符号?

cu可以从串口读取,但我自己的C程序不能

AWK 命令根据另一列中相同的值获取列中的不同值

在 Linux 中屏蔽文件中的位 - 按位运算

Perl/cpan: 找不到 JSON/Parse.pm @INC

sed + 从没有额外空格的文本中删除单词

可以用openmp并行化内存分配删除吗? (c++)

如何在bash中用另一个整数变量增加一个整数变量?

我需要制作一个 awk 脚本来解析文件中的文本.我不确定我是否做得正确

使用 sed 从文本文件中删除特定字符串

在三星 chromebook 上编程

Stripping linux 共享库

在没有root访问权限的情况下安装zsh?

Linux 非阻塞 fifo(按需日志(log)记录)

当命令太长时,命令行会自动覆盖

我如何从 Ubuntu 上的源代码自己构建 python?

如何告诉 CMake 将构建文件放在哪里?

如何在 Linux 中查找所有以 .rb 结尾的文件?

sed - 如何使用 sed 进行正则表达式组