繁体   English   中英

使用Awk处理每个记录具有不同固定宽度字段的文件

[英]Using Awk to process a file where each record has different fixed-width fields

我有遗留系统的一些数据文件,我想用Awk处理。 每个文件都包含一个记录列表。 有几种不同的记录类型,每种记录类型都有一组不同的固定宽度字段(没有字段分隔符)。 记录的前两个字符表示类型,然后您可以知道应该遵循哪些字段。 文件可能如下所示:

AAField1Field2LongerField3
BBField4Field5Field6VeryVeryLongField7Field8
CCField99

使用Gawk我可以设置FIELDWIDTHS ,但这适用于整个文件(除非我在某个记录的基础上缺少某种方式设置它),或者我可以将FS设置为“”并处理文件中的一个字符一段时间,但这有点麻烦。

有没有一种使用Awk从这样的文件中提取字段的好方法?

编辑 :是的,我可以使用Perl(或其他)。 我仍然很想知道是否有一种合理的方法可以用Awk做到这一点。

希望这会引导您朝着正确的方向前进。 假设您的多行记录保证由“CC”类型行终止,您可以使用简单的if-then逻辑预处理文本文件。 我假设您需要在一行上使用fields1,5和7,并且需要一个示例awk脚本。

BEGIN {
        field1=""
        field5=""
        field7=""
}
{
    record_type = substr($0,1,2)
    if (record_type == "AA")
    {
        field1=substr($0,3,6)
    }
    else if (record_type == "BB")
    {
        field5=substr($0,9,6)
        field7=substr($0,21,18)
    }
    else if (record_type == "CC")
    {
        print field1"|"field5"|"field7
    }
}

创建一个名为program.awk的awk脚本文件,并将该代码弹入其中。 使用以下命令执行脚本:

awk -f program.awk < my_multi_line_file.txt 

你可以使用两个通行证:

1step.awk

/^AA/{printf "2 6 6 12"    }
/^BB/{printf "2 6 6 6 18 6"}
/^CC/{printf "2 8"         }
{printf "\n%s\n", $0}

2step.awk

NR%2 == 1 {FIELDWIDTHS=$0}
NR%2 == 0 {print $2}

接着

awk -f 1step.awk sample  | awk -f 2step.awk

您可能需要抑制(或至少忽略) awk的内置字段分隔代码,并使用以下行的程序:

awk '/^AA/ { manually process record AA out of $0 }
     /^BB/ { manually process record BB out of $0 }
     /^CC/ { manually process record CC out of $0 }' file ...

手动处理会有点繁琐 - 我想你需要使用substr函数按位置提取每个字段,所以我每个记录类型的一行更像是每个记录中每行一行类型,加上后续打印。

我认为使用Perl及其unpack功能可能会更好,但awk也可以处理它,尽管很冗长。

你可以使用Perl,然后根据该行的前两个字符选择一个解包模板吗?

更好地使用一些全功能的脚本语言,如perl或ruby。

两个脚本怎么样? 例如,第一个脚本根据第一个字符插入字段分隔符,然后第二个脚本应该处理它?

或者首先在AWK脚本中定义一些函数,它根据输入将行拆分为变量 - 我会这样做,以便重新使用。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM