[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)` ,输出结果顺序就不一定是我们需要的顺序,怎么能固定输出顺序又不将数组下表不写为固定值呢?
- 目录
- 概述
- 第一章 编写第一个Awk命令
- 1.1 什么是Awk命令
- 1.2 第一个Awk命令
- 第二章 Awk的模式匹配
- 2.1 Awk模式语法规则
- 2.2 Awk模式规则详解
- 第三章 Awk的动作规则
- 3.1 Awk动作匹配语法规则
- 3.2 Awk动作规则详解
- 第四章 Awk数据处理方法
- 4.1 数据转换和提炼
- 4.2 数据验证
- 4.3 数据打包与拆包处理
- 4.4 多行数据处理
- 4.5 随机数生成
- 第五章 Awk的输出报告和脚本封装
- 5.1 输出报告
- 5.2 封装查询结果和报告
- 第六章 Awk实现排序算法
- 6.1 插入排序算法实现
- 6.2 快速排序算法实现
- 6.3 堆排序算法实现
- 6.4 拓扑排序算法实现
- 总结