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] : "")
对于我们要输出的每个字段,如果数字在数组中则打印它,
否则,只打印逗号
打印“”
打印一个换行符完成输出记录
删除一个
在读取下一条输入记录之前清空数组
需要一些 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] : "")
对于我们要输出的每个字段,如果数字在数组中则打印它,
否则,只打印逗号
打印“”
打印一个换行符完成输出记录
删除一个
在读取下一条输入记录之前清空数组