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

Using blank-line delimited records and colon-separated fields in awk

我希望能够使用 awk 中的文件,其中记录由空行分隔,每个字段由一个名称后跟一个冒号组成,一些可选的空格是 ignored/discarded,后跟一个值。例如

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 关联数组?

方法一

我们使用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

方法二

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

$ 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

对于其他 awk,您可能需要一次删除一个数组元素,例如:

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