在awk中使用空行分隔记录和冒号分隔字段

时间:2015-06-16 01:58:45

标签: awk etl

我希望能够处理awk中的文件,其中记录由空行分隔,每个字段由一个名称后跟一个冒号组成,一些可选的空格可以忽略/丢弃,然后是一个值。 E.g。

Name: Smith, John
Age: 42

Name: Jones, Mary
Age: 38

Name: Mills, Pat
Age: 62

我了解我可以使用RS=""awk将空白行理解为记录分隔符,并FS="\n"将字段正确分割。但是,我想创建一个namevalue对数组,我可以用它来进一步处理表单

if a["Age"] > 40 {print a["Name"]}

订单通常一致,但由于它会被转储到关联数组中,因此传入的订单不应该重要或被认为是一致的。

如何将数据转换为awk关联数组,并且操作最少?

1 个答案:

答案 0 :(得分:3)

方法1

我们使用split将每个字段分成两部分:键和值。从这些中,我们创建了关联数组a

$ awk -F'\n' -v RS=  '{for (i=1;i<=NF;i++) {split($i,arr,/: /); a[arr[1]]=arr[2];} if (a["Age"]+0>40) print a["Name"];}' file
Smith, John
Mills, Pat

方法2

在这里,我们在分割字段冒号或换行符。然后,我们知道奇数字段是键,偶数字段是值:

$ awk -F':|\n' -v RS=  '{for (i=1;i<=NF;i+=2) {a[$i]=$(i+1);} if (a["Age"]+0>40) print a["Name"];}' file
 Smith, John
 Mills, Pat

改进

是否有可能任何记录都会遗漏某个值?如果是这样,我们应该清除每条记录之间的数组a。在GNU awk中,这很容易。我们只需添加一个删除语句:

awk -F':|\n' -v RS=  '{delete a; for (i=1;i<=NF;i+=2) {a[$i]=$(i+1);} if (a["Age"]+0>40) print a["Name"];}' file

对于其他awks,您可能需要一次删除一个元素,如:

for (k in a) delete a[k];