AWK
awk:报告生成器,格式化文本输出
gawk:模式扫描和处理语言
基本语法:
options:选项
program:awk的语言
var=value:赋值给var
file:参数
awk [options] 'program' var=value file...
awk [options] -f programfile var=value file...
awk [options] 'BEGIN{action} pattern{ action;...}END{action;...}' file..
选项:
-F 指定分隔符
-v var=value:自定义变量
awk语言
基本格式:awk [options] 'program' file....
program:pattern{action statements;...}
pattern和action:
pattern部分决定动作语句何时触发及触发事件
BEGIN:文件处理之前就执行一个动作
END:当所有文件处理结束后执行一个动作
action statements对数据进行处理,放在{}内指明
print,printf
分隔符、域和记录
awk执行时,由分隔符分隔的字段(域)标记$1,$2...$n成为域标识;$0为所有域
文件的每一行称为记录,也可以用别的作为记录的分隔符
省略action,默认执行print $0
awk工作原理
第一步:如果有BEGIN{action;...}优先执行BEGIN
第二步:从命令的执行结果或者文件读取一行,然后执行pattern{action;...},逐行处理
第三步:执行END{action;....}
awk
item=要打印的字符
print格式:print item1,item2,...
注意:
(1)逗号分隔符
(2)输出的各item可以字符串,也可以是数值;当前记录的字段、变量或awk的表达式
(3)如省略item,相当于print $0
awk变量
field 域,字段,列column,属性(一个意思)
行,记录,record(一个意思)
变量:内置和自定义变量
使用变量时,需添加-v选项
FS:字段的分隔符,默认为空白字符
awk -v FS=':' '{print $1,FS,$2}' passwd (指定FS变量值为:打印passwd文件的第一列和第二列,逗号是作为空白符的)
OFS:输出分隔符的定义
awk -v OFS="+" '{print $1,$2}' passwd(指定OFS变量值为+,打印passwd文件的第一列和第二列,输出分隔符是+)
RS:指定分开记录的分隔符
记录:默认回车换行算一条记录
awk -v RS=";" '{print $2}' f1.txt中的值为 aa bb cc;ee
ff oo;xx
yy zz (指定RS变量值为;打印f1.txt文件的第二列,结果为bb ff yy)
ORS:指定记录输出的分隔符
awk -v RS=" " -v ORS="###" '{print}' passwd(默认以回车换行区分每条记录,ORS指定区分每条记录的分隔符)
NF:字段个数
awk -F: '{print NF}' passwd(逐行处理,显示的全是7)
awk -F: '{print $NF}' passwd(逐行处理,显示第7列的数据,因为NF是7)
awk -F: '{print $(NF-1)}' passwd(逐行处理,显示7-1列的数据)
NR:记录号
awk '{print NR,$0}' passwd(逐行处理,每一行都打印,并且显示每一行的行号)
FNR:文件分别计数
awk '{print FNR,$0}' /etc/fstab /etc/issue(两个文件分别显示所有行并且显示行号)
FILENAME:当前文件名
awk '{print FNR,FILENAME,$0}' /etc/fstab /etc/issue(两个文件分别显示所有行并且在前面显示文件名称)
ARGC:参数个数
awk '{print ARGC}' /etc/fstab /etc/issue(查看awk的参数)
ARGV:数组,显示命令行awk算第一个参数,跳过print部分,后续为第二个参数,第三个参数
awk '{print ARGV[0]}' /etc/fstab /etc/issue
print中也可以定义变量
awk的-f选项可以读取文件,文件中写入的是'{print}'等一系列数据
printf命令
格式化输出:printf "FORMAT",item1,item2,....
(1)必须指定FORMAT
(2)不会自动换行,需要显示给出换行控制符,\n
(3)FORMAT中需要分别为后面每个item指定格式符
格式符:与item一一对应
%c:显示字符的ASCII码
%d,%i:显示十进制整数
%e,%E:显示科学计数法数值
%f:显示为浮点数
%g,%G:以科学计数法或浮点形式显示数值
%s:显示字符串
%u:无符号整数
%%:显示%自身
修饰符:
#[.#]:第一个数字控制显示的宽度;第二个#表示小数点后精度,%3.1f
-:左对齐(默认右对齐) %-15s(前面空出15个宽度并且左对齐显示)
+:显示数值的正负符号%+d
操作符:
x+y, x-y, x*y, x/y, x^y, x%y
-x: 转换为负数
+x: 转换为数值
赋值操作符:
=, +=, -=, *=, /=, %=, ^=
++, --
比较操作符:
==, !=, >, >=, <, <=
模式匹配符:
~:左边是否和右边匹配包含 !~:是否不匹配
可以使用扩展的正则表达式,""中写正则表达式,或者//中写正则表达式
例子:awk –F: '$0 ~ /^root/' /etc/passwd 匹配文件中以root开头的行
awk -F: '$3>=0 && $3<=1000 {print $1}' /etc/passwd (打印匹配第三个字段大于0并且第三个字段小于1000)
awk -F: '$3==0 || $3>=1000 {print $1}' /etc/passwd (打印匹配第三个字段等于0或者第三个字段大于1000)
awk -F: '!($3==0){print $1}' /etc/passwd (打印第三个字段不等于0的行)
awk -F: '!($3>=500){print $3}' /etc/passwd (打印第三个字段不等于500的字段的行)
awk当中变量为""为假,为0的时候为假,有值则为真
条件表达式(三目表达式:用三个表达式,分别用?:分开分成三段)
例子:awk -F: '{$3>=1000?usertype="common user":usertype="sysuser";printf "%-15s:%-30s %d \n",usertype,$1,$3}'
awk PATTERN
PATTERN:就是花括号前面的部分
(1)如果没有指定:空模式,匹配每一行
(2)/正则表达式/
(3)关系表达式,结果为真才会被处理
真:结果为非0值,非空字符串
加:结果为空字符串或0值
(4)line ranges:行范围
'/条件/,/条件/' 第一个条件必须要匹配,第二个条件没有的话则会匹配到结尾
(5)BEGIN/END模式
BEGIN{}:处理文件之前处理一次
END{}:在文件处理完成之后处理一次
awk action
常用的action分类
(1)算数,表达式
(2)if,while等
(3)组合语句就是?:分开的
(4)输入语句
(5)输出:print
if语句
语法:if(表达式){执行的操作;....}[else 执行操作]
while循环:当字段个数过多并且都要执行的时候可以使用
语法:while(表达式){执行的操作;...}
条件"真",进入循环;条件"假"退出循环
do-while循环
语法:do{执行操作;}while(表达式)
意义:无论真假,至少执行一次
next:
提前结束对本行处理而直接进入下一行处理(awk自身循环)
awk数组
关联数组:array[下标自定义]
(1)可使用任意字符串;字符串要用双引号括起来
awk '!arr[$0]++' 文件名(去掉重复行操作)
遍历数组.
for(var in array){for-body}
awk '{IP[$1]}END{for(i in IP)print i,IP[i]}' /var/log/access_log 统计IP地址的连接次数
awk函数
数值处理:
rand():返回0和1之间的一个随机数,但是如果单独打印rand()是不能生成随机数的与srand()函数结合使用,默认生成的浮点数,生成整数如下
例子:awk 'BEGIN{srand();print int(rand()*100)}':生成随机整数
字符串处理:
length("指定字符串"):返回指定字符串长度
sub(r,s,要处理的字符串):对要处理的字符串进行搜索r表示修改的字符串,s是修改后的字符串,只替代第一个匹配到的
gsub:是将匹配到的全部替换
split(s,arry,r):对字符串s进行切割,使用r作为分隔符,将切割后的结果保存到arry的数组中,成为了数组的值
自定义函数
格式:
function "name" (参数1,参数2,.....相当于shell的$1,$2,$3....){
代码
return "表达式"
}
调用的参数是实际参数,命名的时候是形式参数;实际参数和形式参数的名称可以不同,但数量要相同
使用system调用bash命令
例子:awk BEGIN'{system("hostname")}'
如果是awk中定义的变量awk要用system的echo调用的话将命令加入到双引号中