Awk:根据当前列值创建列

Awk: Create columns based on current column value

需要一些 awk-fu!我有以下数据结构:

ybcxl,05,06,07,08,09,10,11  
yxxu,01  
yxxu,03,05,06,07,08,09,10,11  
ybban,01,03,04,05,06,07,08  
zxvhu,01,02,03,04,05,06,07,08,09,10,11,12  

每行应该有 13 列。从第 2 栏开始,我需要评估价值。该值应始终为列号减 1。换句话说,第 2 列的值为 1。我需要创建列(通过插入逗号),以便每一行都有适当数量的列,现有值的顺序正确(列号减 1,第 1 条记录的偏移量)。

更正数据示例:

yxxu,01,,,,,,,,,,  
yxxu,,,03,,05,06,07,08,09,10,11,  
$ cat af.txt
ybcxl,05,06,07,08,09,10,11
yxxu,01
yxxu,03,05,06,07,08,09,10,11
ybban,01,03,04,05,06,07,08
zxvhu,01,02,03,04,05,06,07,08,09,10,11,12

$ cat af.awk
BEGIN { FS="," }
{
    printf "%s", 
    for (i=2; i<=NF; ++i) a[$i+0] = $i
    for (i=1; i<=12; ++i) printf ",%s", (i in a ? a[i] : "")
    print ""
    delete a
}

$ awk -f af.awk af.txt
ybcxl,,,,,05,06,07,08,09,10,11,
yxxu,01,,,,,,,,,,,
yxxu,,,03,,05,06,07,08,09,10,11,
ybban,01,,03,04,05,06,07,08,,,,
zxvhu,01,02,03,04,05,06,07,08,09,10,11,12

测试以确保所有行都有 13 列:

$ awk -f af.awk af.txt | awk -F, '{ print NF }'
13
13
13
13
13

测试以确保列号比它们对应的字段值(如果存在)多 1:

$ awk -f af.awk af.txt | awk -F, '{ error = 0; for(i=2;i<=13;++i) { if ($i && i != ($i + 1)) error = 1 } print (error ? "ERROR!" : "GOOD!")}'
GOOD!
GOOD!
GOOD!
GOOD!
GOOD!

解释:

开始 { FS="," }
将字段分隔符设置为逗号

printf "%s", $1
输出第一个字段(使用 printf 避免换行)

for (i=2; i<=NF; ++i) a[$i+0] = $i
将记录中存在的所有数字存储到一个数组中,使用它们的数字 等价于索引($i+0 将字符串转换为数字)

for (i=1; i<=12; ++i) printf ",%s", (i in a ? a[i] : "")
对于我们要输出的每个字段,如果数字在数组中则打印它, 否则,只打印逗号

打印“”
打印一个换行符完成输出记录

删除一个
在读取下一条输入记录之前清空数组