[TOC] # 多行记录的数据处理 > 我们实际处理的数据并不会都是一行就是一条记录,有的时候我们会遇到多行数据作为一条记录的情况,那么这种情况要如何使用Awk程序来处理呢? 本节就来介绍多行的记录处理方法。 ## 示例: 处理格式固定、空白行作为记录分隔符数据 > 我们之前了解了`RS`变量作用是设置记录分隔符的,当`RS`设置为""空时,`FS`变量默认可以为连续的空白符、Tab制表符或者换行符,当我们设置`FS`为'\n'换行符时,每一行数据就被识别为一个字段了,直到遇到空行结束一条记录。 以下面的数据为例: ``` $ cat person.txt 张三 30 165 中国北京市朝阳区 李四 25 170 中国河北省郑州市 ``` 上面的数据是四行数据为一个人的信息,第一行为姓名,第二行为年龄,第三行为身高,第四行为所在地区,每条信息记录都是通过空行分隔开。 接下来我们来用Awk程序解析并格式化输出信息: ``` #!/usr/bin/awk -f BEGIN{ FS="\n" RS="" }{ printf("姓名:%-10s ,年龄: %5d ,身高: %5d ,地址: %s\n", $1, $2, $3, $4) } ``` **执行命令:** ``` $ ./multiline.awk b.txt ``` **输出结果:** ``` 姓名:张三 ,年龄: 30 ,身高: 165 ,地址: 中国北京市朝阳区 姓名:李四 ,年龄: 25 ,身高: 170 ,地址: 中国河北省郑州市 ``` 这个示例可以做到将多行记录格式化输出为一行记录,加入我们已经有一个可以处理单行记录的Awk程序了,那么我们要做的可能有两种: 1. 修改已经有的Awk程序的`RS`和`FS`变量后再处理数据。 2. 再编写一个类似上面的示例,将多行记录格式化输出为单行记录。 两种办法各有优点,你可以根据自己倾向来选择。 ## 示例:处理格式不固定、空白符作为记录分隔符数据 > 对于格式顺序固定的多行记录处理方法我们已经掌握了,那么对于格式顺序不固定的又需要如何处理呢?比如四列数据年龄位置可能在身高后,也可能在地址后,这时候就需要在行开始位置为每行数据含义增加一些关键词标识了。 我们来看下这个示例: ``` $ cat person.txt 姓名 张三 年龄 30 身高 165 地址 中国北京市朝阳区 身高 170 地址 中国河北省郑州市 姓名 李四 年龄 25 ``` 我们的Awk可以这样实现: ``` /^姓名/{ name = $2 } /^年龄/{ age = $2 } /^身高/{ height = $2} /^地址/{ addr = $2 } /^$/{ printf("%s %s %s %s\n", name, age, height, addr)} ``` 执行命令: ``` ./multline2.awk persion.txt ``` 输出结果: ``` 张三 30 165 中国北京市朝阳区 李四 25 170 中国河北省郑州市 ``` 我们也可以通过设置`RS`和`FS`的方法做一个通用的示例: ``` $ cat multiline4.awk #!/usr/bin/awk -f function prinfo(i){ for(i = 1; i <= NF; i++) f($i) for( i in res) printf("%s ", res[i] ) print "" } function f(n){ split(n, arr, " ") return res[arr[1]] = arr[2] } BEGIN{ FS="\n"; RS = ""; } { prinfo() } ``` 思考问题: 1. 上面的示例由于使用了`for( i in res)` ,输出结果顺序就不一定是我们需要的顺序,怎么能固定输出顺序又不将数组下表不写为固定值呢?