awk:
文本处理三剑客:grep,sed,awk;
grep系:grep,egrep,fgrep;基于pattern进行过滤文本;
sed:流编辑器,行编辑器;模式空间,保持空间;
awk:报告生成器,格式化文本输出;
AWK:
Alfred Aho,贝尔实验室;
Peter J Weinberger,贝尔实验室;
Brian Kernighan,贝尔实验室,K&R
CentOS RHEL系awk,GNU AWK,gawk;
Debian系awk,New awk,nawk
GNU awk——gawk
gawk - pattern scanning and processing language
基本格式:
awk [options] 'program' file...
program:pattern{action statements;...}
pattern:部分决定动作语句何时触发及通过什么事件来触发;
BEGIN,END
action statement对数据进行处理,通常放在一对{}之中;
print,printf
分隔符:awk对数据进行处理时,会根据特定的标识对数据进行分段,这种特定标识就是分隔符,默认是空白字符;
字段:经过分隔符分隔之后的每一个分段,都称为一个字段(Field);默认awk会使用内置位置变量来存储各个字段的值;这些变量就是$1,$2,...$N;
记录:有换行符分隔的数据中的每一行,就是一个记录;在awk处理数据时,使用$0保存整行的内容;
awk工作原理:
1.首先,执行BEGIN{action statements}语句块中的语句;
2.其次,从文件中或者从标准输入读取一行,然后执行pattern{action statements}语句块;逐行重复处理该过程,直到数据全部被读取完毕;
3.在其他语句执行完成后,在退出awk程序之前,执行END{action statements}语句块;
注意:
1).BEGIN语句块在awk开始处理数据之前就需要执行;此语句块是可选语句块;
2).END语句块在awk处理完所有的数据之后,才会被执行;此语句块是可选语句块;
3).pattern语句块中的通用命令是最重要的部分,也是可选的;如果没有提供pattern语句块,则默认执行{ print }语句,显示数据的每一行;awk读取到的每一行都会执行一次pattern语句块的内容;
awk的基本用法:
常用选项:
-F:用来指明此次数据处理的字段分隔符,默认为空白字符;
-v var=value:用于自定义变量和为自定义变量赋初始值;
常用的ACTION:
1.print:标准格式显示;
print item1,item2,...
print命令的要点:
a.逗号分隔;
b.输出的各item可以是字符串,可以是数字,可以是当前记录中的字段,可以是变量,可以是awk表达式;
c.如果省略了item,就输出整行,相当于{print $0};
示例:
~]# awk -F: '{print $1,$3,$7}' /etc/passwd
~]# echo -e "1 2 3\n4 5 6\n7 8 9" | awk '{print $2}'
2.变量:
内建变量:
FS:input field seperator,输入字段分隔符,默认空白字符;
示例:
~]# awk -v FS=':' '{print $1}' /etc/passwd
OFS:outpit field seperator,输出字段分隔符,默认空白字符;
示例:
~]# awk -v FS=':' -v OFS=':' '{print $1,$3}' /etc/passwd
RS:input record seperator,输出记录分隔符,换行;
注意:即使指定了新的输出记录分隔符,即变为换行;
示例:
~]# awk -v RS='/' '{print $0}' /etc/passwd
ORS:output record seperator,输出记录分隔符;不换行
NF:number of field,字段数量;
示例:
~]# awk -v FS=':' '{print NF}' /etc/passwd
~]# awk -v FS=':' '{print $NF}' /etc/passwd
~]# awk -v FS=':' '{print $(NF-1)}' /etc/passwd
NR:number of record,行数;鉴于awk遍历文件每行的特性,可以将该变量理解为行号;
示例:
~]# awk '{print NR}' /etc/passwd
FNR:file number of record,分别统计各个文件的行数,行号;
示例:
~]# awk '{print FNR}' /etc/passwd /etc/fstab
FILENAME:输出当前正在处理的文件的文件名;每行显示一个;
示例:
~]# awk '{print FILENAME}' /etc/passwd /etc/fstab
ARGC:argument count,整个命令行中的参数的数量;包括命令本身;
示例:
~]# awk '{print ARGC}' /etc/passwd /etc/fstab /etc/issue
ARGV:数组,argument value,保存了命令行中各个参数的具体内容;
示例:
~]# awk '{print ARGV[1]}' /etc/passwd /etc/fstab /etc/issue
自定义变量:
定义方式:
-v var=value
注意:变量名区分字符大小写;
示例:
~]# awk -v var1='hello' -F: '{print var1 ,$1}' /etc/passwd
3.printf命令:
格式化输出命令:printf "FORMAT" item1,item2,...
要点:
1) 必须给出合适的FORMAT;
2) 默认不自动换行,需要显式给出换行控制符(\n);
3) FORMAT中需要为后面的每一个item指定一个格式化符号;
格式符:
%c:显示字符的ASCII码;
%d,%i:显示十进制整数;
%f:显示浮点数字;
%e,%E:使用科学计数法显示数字;
%g,%G:使用科学计数法显示浮点数字;
%s:显示字符串;
%u:显示无符号整数;
%%:显示%自身;
修饰符:
#[.#]:第一个数字用来控制显示宽度;第二个数字表示小数点的精度;
如:%3.1f %5s
-:表示采用左对齐机制;默认是右对齐; %-15s
+:显示数字的正负符号;%+d
示例:
~]# awk -F: '{printf "%-20s: %-5s\n",$1,$3}' /etc/passwd
4.操作符:
算术操作符:
x+y, x-y, x*y, x/y, x^y, x%y
-x:将正数转换为负数;
+x:将字符串转换为数值;
字符串操作符:
没有符号的操作符,表示字符串连接之意;
赋值操作符:
=, +=, -=, *=, /=, %=, ^=
++, --
比较操作符:
>, >=, <, <=, ==, !=
模式匹配操作符:
~:左侧的字符串是否能够被右侧的模式所匹配;
!~:左侧的字符串是否不能够被右侧的模式所匹配;
示例:
~]# awk -F: '$3==1000{print $0}' /etc/passwd
~]# awk -F: '$NF~/bash/{print $0}' /etc/passwd
逻辑操作符:
&&
||
!
示例:
~]# awk -F: '$3>=500&&$3<=1000{print}' /etc/passwd
条件表达式:
condition(selector)?if-true-expression:if-false-expression
示例:
~]# awk -F: '{$3>=1000?usertype="Common User":usertype="Super or System User";printf "%-20s: %-20s\n",usertype,$1}' /etc/passwd
5.PATTERN:
1) empty:空模式,处理文件中的每一行;
2) [!]/REGEXP/:仅处理[不]能被PATTERN匹配到的行;
示例:~]# awk '[!]/^r/{print}' /etc/passwd
3) 关系表达式:$3>=1000, $NF~/bash/
4) 行的范围:
关系表达式:($3>=500&&$3<=1000)
/regexp1/,/regexp2/:从被regexp1匹配的行开始到被regexp2匹配的行结束,有多少这一类匹配结果,就显示多少次;
示例:~]# awk '/^r/,/^a/{print}' /etc/passwd
5) BEGIN/END模式:
BEGIN{}:仅在开始处理文件中的第一行文本之前执行一次的语句块;
示例:
~]# awk -F: 'BEGIN{printf "%20s %5s\n","Username","UserID"}{printf "%20s %5s\n",$1,$3}' /etc/passwd
注意:在输出特定格式的表头时,常用此语句块;
END{}:仅在文本处理完成但命令尚未退出时执行一次的语句块;
示例:
~]# awk -F: 'BEGIN{printf "%20s %5s\n","Username","UserID"}{printf "%20s %5s\n",$1,$3}END{print "========================\n",NR " users"}' /etc/passwd
6.常用的ACTION:
1.表达式(Expression)
2.组合语句(Cpmpound Statement)
3.输入语句(Input Statement)
4.输出语句(Output Statement)
5.控制语句(Control Statement)
7.控制语句:
if (condition) statement [ else statement ]
while (condition) statement
do statement while (condition)
for (expr1; expr2; expr3) statement
for (var in array) statement
break
continue
delete array[index]
delete array
exit [ expression ]
{ statements }
switch (expression) {case value|regex : statement...[ default: statement ]}
1) if-else:
语法:if (condition) {statement} [ else {statement} ]
使用场景:对awk取得的整行或某个字段做条件判断;
示例:
~]# awk -F: '{if($3>=1000) {print $1} else {print $1,$3}}' /etc/passwd
2) while循环:条件为真,进入循环;条件为假,退出循环;
语法:while (condition) statement
使用场景:对一行内的多个字段逐一做类似的处理时;对数组中的各个元素遍历及处理时;
示例:
~]# awk '/^[[:space:]]*linux16/{i=1;while(i<=NF) {printf "%s: %d\n",$i,length($i);i++}}' /etc/grub2.cfg
3) do...while循环:
语法:do statement while (condition)
意义:同while循环,但至少执行一次循环体中的语句;
4) for循环:
语法:for (expr1; expr2; expr3) statement
expr1:变量赋初值;
expr2:条件判断;
expr3:变量值的递增或递减调整;
示例:
~]# awk '/^[[:space:]]*linux16/{for(i=1;i<=NF;i++) {printf "%s: %d\n",$i,length($i)}}' /etc/grub2.cfg
5) break 和 continue
break [n]
continue:跳过本次循环,直接进入下次循环;
6) next语句:
提前结束对本行的处理,而直接进入下一行;
示例:
~]# awk -F: '{if($3%2!=0) next;print $1,$3}' /etc/passwd
8.数组(Array)
关联数组:array[index_expression]
index_expression:
1) 可以使用任意的字符串,字符串必须使用双引号;
2) 如果某数组元素事先不存在,当引用该元素时,awk会自动创建此元素,并且为该元素赋"空字符串"作为其初始值;空字符串取值为0
注意:如果想要判断数组中某个元素是否存在,一般会使用"index in array"格式进行; index in array:数组索引name
示例:
~]# awk 'BEGIN{name["leader"]="zhang";name["mem1"]="li";name["mem2"]="wang";print name["leader"]}'
查看已连接状态下,同一客户端的连接数量:
~]# ss -tn | awk '/^ESTAB\>/{print $NF}' | awk -F: '{state[$1]++}END{for(s in state){print state[s],s}}'
9.函数:
内建函数:
length():计算字符串长度
split(string,array[,fieldsep])
示例:
~]# awk '{split($0,user,":");print user[1]}' /etc/passwd
自定义函数: