目录
awk
是Linux Shell文本分析工具之一,功能非常强大。其中,在文本文件处理以及报表生成上,
awk
是无可替代的。
1. 基本介绍
文件解析依据,awk
认为文本文件
都是结构化的
。何为结构化呢?也就是,定义每个输入行为一条记录,而行中每个字符串定义为一个域(或者段),域与域之间使用分割符
界定。主要用途,包括流控制、数学运算、进程控制、内置的变量和函数、循环和判断。
1.1. 工作原理
awk
对每行进行拆分,用相应命令对拆分出来的“段”
进行处理。
- 行工作模式,读入文件的每一行,会把一行的内容,存到
$0
里 - 使用内置的变量
FS
(段分隔符,默认用的是空白字符)分割行,把分割出来的每个段存到相应的变量$(1-100)
- 输出的时候,按照内置变量
OFS
(out FS)输出 - 读入下一行继续操作
[root@master-zeus ~]# echo "this is a hadoop book" > awk.txt
[root@master-zeus ~]# awk '{print $2,$1,$3,$4,$5}' awk.txt
is this a hadoop book
1.2 代码块
通常情况下,awk
只会处理每一输入行,并执行一段代码块。但是,有些需要在awk开始处理输入行之前执行一些内置变量设置初始化,这是就需要用到BEGIN
代码块。与之对应的是END
代码块,用于在所有输入都处理完成后awk运行的代码块。也就是说,从运行看,awk由处理前调用
、处理过程
、处理结束调用
组成。其中,处理过程位于BEGIN、END之间。
[root@master-zeus ~]# vim search.awk
BEGIN {
FS=":"
print "Init Finish"
}
/root/
{
++rootUserCnt
}
/bash/
{
++bashCnt
}
{
print "User -> ", $1
}
END {
print "Account nologin User Sum -> " rootUserCnt
print "Account contain bash Sum -> " bashCnt
}
[root@master-zeus ~]# awk -f search.awk /etc/passwd
Init Finish
User -> root
...
Account nologin User Sum -> 3
Account contain bash Sum -> 3
1.3 模式匹配
处理过程中,如果awk
发现处理逻辑之前包括正则表达式,那么会进行正则匹配,匹配得上进行相应逻辑处理,其语法如下:
/正则表达式/ {匹配处理逻辑}
1.4 变量
awk
与语言类似,也是提供代码编程,比较关键的就是变量定义。awk提供2中变量支持,其中一种是内建变量,其次就是自定义变量。
1.4.1 常用内置变量
内置变量 | 说明 |
---|---|
$0 | 当前记录,即一行记录 |
$1~$n | 当前记录第n 个字段,字段由FS 分隔 |
FS | 全称Fields Space ,输入字段分隔符,默认为空格 |
NF | 全称Number Fields ,当前记录字段数量,也就是包含多少列 |
NR | 全称Number Rows ,已读记录数,也就是行号,从1 开始 |
RS | 全称Rows Space ,输入记录分隔符,默认为换行符 |
OFS | 全称Output Fields Space ,输出字段分隔符,默认也是空格 |
ORS | 全称Output Rows Space ,输出记录分隔符,默认为换行符 |
ARGC | 全称Argument Count ,命令行参数个数 |
ARGV | 命令行参数数组 |
FILENAME | 当前记录文件名 |
IGNORECASE | 如果为真,匹配忽略大小写 |
ARGIND | 当前被处理文件ARGV 标志符 |
CONVFMT | 数字转换格式,默认%.6g |
ENVIRON | UNIX环境变量 |
ERRNO | UNIX系统错误消息 |
FIELDWIDTHS | 输入字段宽度空白分隔字符串 |
FNR | 当前记录数 |
OFMT | 数字的输出格式,默认%.6g |
RSTART | 被匹配函数匹配的字符串首 |
RLENGTH | 被匹配函数匹配的字符串长度 |
SUBSEP | \034 |
1.4.2 自定义变量
在awk
中,自定义变量包括数组
和数值
,变量不需要先申明自使用。对于数组,awk支持数字或者字符串作为索引,其语法如下:
变量名[数字/字符串]=值
对于数值变量,直接对其进行操作处理,但需要注意的是,awk在使用变量时都会有一个空字符串初始值,但需要数值时,会自动变为0
。数值变量申明语法如下:
变量名=值
2. 输出
在awk
中,如果需要将内容输出,可以调用print
或者printf
进行输出。需要注意的是,只有printf
才能进行format
输出。
[root@master-zeus ~]# echo 23.22 11.22 123.3 \
| awk '{printf "%.2f %.2f %.2f\n", $1, $2, $3}'
23.22 11.22 123.30
[root@master-zeus ~]# echo 23.22 11.22 12.33 | awk '{print $1, $2, $3}'
23.22 11.22 12.33
其中,printf format
如下:
格式化 | 说明 |
---|---|
%c | ASCII字符 |
%s | 字符串 |
%d | 十进制整数 |
%ld | 十进制长整数 |
%u | 十进制无符号整数 |
%lu | 十进制无符号长整数 |
%x | 十六进制整数 |
%lx | 十六进制长整数 |
%o | 八进制整数 |
%lo | 八进制长整数 |
%e | 科学计数法(e 计数法)表示的浮点数 |
%.mf | 浮点数,m在这里插入代码片 表示小数点位数,可选 |
%g | 选用e 或f 中较短的一种形式 |
printf
修饰符:
修饰符 | 说明 |
---|---|
- | 左对齐 |
+ | 使用d 、e 、f 和g 表达整数时,显示数值符号 |
# | 八进制前面加0 ,十六进制前面加0x |
0 | 用0 ,而不是空白符填充索要显示的数值 |
3. 控制语句
awk
作为一门语言,自然支持语言的3种基本元素:顺序、判断和循环。
3.1 if语句
语法:
if(表达式) {
代码块
} else if(表达式) {
代码块
} else {
代码块
}
3.2 while条件
语法一:
while(表达式) {
代码块
}
语法二:
do {
代码块
} while(表达式)
3.3 for循环
语法:
for(初始化段; 表达式; 增量) {
代码块
}
3.4 break/continue
break
和continue
,可以集合while
或者for
跳出循环,其中break
表示跳出循环,continue
表示跳入下次循环。
4. 自定义函数
语法:
function 函数名(参数) {
代码块
return 返回值
}
注意,自定义函数需要放在BEGIN之前。
5. 字符串函数
函数 | 描述 |
---|---|
sub(/reg/, new_substr, str) | 替换匹配第一个字符串,返回替换数量 |
gsub(/reg/, new_substr, str) | 替换所有匹配的字符串,返回替换数量 |
index(str, substr) | 返回substr在str中的索引 |
length(str) | 返回字符串长度 |
match(str, /reg/) | 如果能从str中找到匹配的字符串,则返回匹配的位置,否则返回0 |
split(str, array, sep) | 拆分字符串 |
substr(str, start, [length]) | 获取指定位置子串 |
tolower(str) | 转换字符串为小写 |
toupper(str) | 转换字符串为大写 |