首页 > 解决方案 > 使用 awk 检查一行中的多个位置的数据

问题描述

我正在尝试提取一些最初来自大型机的信息。这些行都是 ASCII 字符数据,但每一行都被认为是多段的,因此具有不同的行长。字段是长度分隔的。行中有一个字段指示变量部分预期有多少行段。我想做的是在这些变量段中寻找指标的存在,并从中提取一些数据。

一个简化的例子如下所示;

UUID12345 1   ABC 1 345  
UUID23456 2   XYZ 4 763 ABC 4 678  
UUID34567 3   XYZ 4 763 ABC 2 456 QRS 2 456  
UUID45678 2   DEF 1 345 TUV 8 111 
UUID56789 0

第二列指示预期有多少段。最多可以有99个段,但实际上少于 10 个。在上面的示例中,每个段将包含 10 个字节,例如从第一行的 ABC 位置开始。我要提取的是每行的第一列以及包含 ABC 的任何段的最后 3 个字符的值。

因此,上述行的示例输出可能是;

UUID12345 345  
UUID23456 678  
UUID34567 456
UUID45678 
UUID56789 

我知道一些非常基本的 awk,并且可以查找一行的特定部分,但不知道如何实现我需要的。例如,以下为我提供了提取第一行的能力,但只能通过查看特定位置,并且没有考虑指示可变段数的第二列。

awk '{ if (substr($0, 0, 4)=="UUID" && substr($0, 15, 3)=="ABC") {print substr($0, 0, 9) " " substr ($0, 21,3)}}' <<< "UUID12345 1   ABC 1 345"

编辑

根据我在下面对 Ed Morton 的评论,这就是我最终得到的对我有用的东西(其中 test.txt 是上面显示的示例);

awk '{segs=substr($0, 11, 1); acc=substr($0, 1, 10); startCol=15; val=""; for(i=startCol; i<startCol+(10 * segs); i+= 10) if (substr($0, i, 3)=="ABC") val=substr($0, i + 6, 3); print acc " " segs " " val}' test.txt

标签: parsingawkdynamic

解决方案


$ awk '{val=""; for (i=3; i<NF; i+=3) if ($i=="ABC") val=$(i+2); print $1, val}' file
UUID12345 345
UUID23456 678
UUID34567 456
UUID45678
UUID56789

如果这还不是您所需要的,那么编辑您的问题以提供更具代表性的示例输入/输出,从而更好地满足您的所有要求。


推荐阅读