[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 拓撲排序算法實現
- 總結