文本处理工具:grep,sed,awk
awk:报告生成器,格式化文本输出
AWK: Aho ,Weinberger,Kernighan
gawk:GNU awk
gawk – pattren scanning and processing language
基本语法:gawk [options ] ‘program’ FILE….
program:PATTERN{ACTION STATEMENTS}
语句之间用分号分隔
选项:
-F:指明输入时用到的字段分隔符
-v:var=value:自定义变量
-
print
print item1,item2,…..
要点:
1.以逗号作为分隔符
2.输出的各item可以是字符串,也可以是数字。也可以是当前记录的字段,变量或者awk的表达式
3.如果省略item,相当于print $0
实例:
注意print里面的字符要用引号 引起来
如果是变量就不要用引号了
省略item相当于print $0,而print “”相当于空,而print “ ”表现是空格
2.变量
a,内建变量(分隔符)
FS:inuput field seperator,默认为空白字符
OFS: output field seperator,默认为空白字符
RS:inuput record seperator,输入的换行符
ORS:output record seperator,输出的换行符
因为此处只定义了输入时换行符为“”,并没有定义输出换行符,所有默认,在输出的时候空格时要换行
,原默认要换行的时候也会换行
NF:number of field,字段数量
{print NF} 显示字段数 {print 1}
,{print $NF}显示最后一个字段,类似于{print $1}
NR: number of field,行数 (如果两个文件一起显示,会直接连在一起,不会分开计数)
{print NR} 显示行数
FNR:file number of field, 各文件分开计数行数
FILENAME:当前文件名
ARGC:命令行参数的个数
ARGV:数组,保存的是命令行所给定的各参数
b.自定义变量
1.-v var=value
变量名区分大小写
2.在program中直接定义
3.printf命令
格式化输出:printf FORMAT ,item1,item2,….
1.FORMAT是必须要给出的
2.不会自动换行,需要显示给出换行控制符,\n
3.FORMAT需要分别为后面的每个item指定一个格式化符号
格式符:
%c:显示字符的ASCII码
%d,%i:显示十进制整数
%e,%E:科学计数法数值显示
%f:显示为浮点数
%g,%G:以科学计数法或浮点形式显示数值
%s:显示字符串
%u:无符号整数
%%:显示%自身
换行符记得加上,不然看起来就很蠢了!!
每个item都要有一个FORMAT,否则item就不成立了,不显示了
修饰符:
#[.#]格式符:
例如%3.1f==>第一个数字控制显示宽度,第二个数字表示小数点后的精度
-:表示左对齐,默认为右对齐
+:表示数值的符号
表示左对齐
默认为右对齐
4.操作符
算术运算操作符
+,-,*,/,^,% 依次为加减乘除 次方取模
-x:负值
+x:转换为数值
字符串操作符:没有符号的操作符,字符串连接
赋值操作符
=,+=,-=,*=,/=,^=,%=
比较操作符:
>,>=,<,<=,!=,==
模式匹配:
~:是否匹配
!~:是否不匹配
逻辑操作符:
&&: 与
||:或
!:非
显示/etc/passwd文件中uid=0或者大于1000的行显示第1,3列,分隔符为”:“
显示/etc/passwd文件中uid大于等于0小于等于1000的行显示第1,3列,分隔符为”:“
显示/etc/passwd文件中uid不等于0的行显示第1,3列,分隔符为”:“
函数调用:
function_name(argu1,argu2,…..)
条件表达式:
selector ? if-true-expression:if-false-expression
如果为真执行true,否则执行false
实例:
如果uid大于1000,则usertype为common,否则为system,,输出每行第一列及变量usertype
awk -F: '{$3>=1000?usertype="common":usertype="system";printf "%15s:%-s\n",$1,usertype}' /etc/passwd
5.PATTERN
1.empty:空模式,匹配每一行;
2./regular expression/:仅处理被此处的模式匹配的行
!/regular expression/:仅处理被此模式匹配的行之外的行
例:显示以UUID开头的行,显示第一列,可个为分隔符
显示不以UUID开头的行,显示第一列,可个为分隔符
3.relational expression:关系表达式,结果有”真“有”假“,结果为”真“才会被处理
真:结果为非0值,非空字符串
假:结果为空字符串或0值
示例:
4.line ranges:行范围
startline,endline: /pat1/,/pat2/不支持直接给出数字格式
显示从以root开头的行开始,到以nobody开头的行结束,显示第一列,以”:“为分隔符
显示行号小于10或者大于40的行,取出第一列,分隔符为”:“
5.NEGIN/END模式
BEGIN{}:仅在开始处理文件中的文本之前执行一次
END{}:仅在文本处理完成之后执行一次
示例:
结果为真处理,为假不处理
显示偶数行和奇数行
此例来解释为何上面是奇数和偶数
说明:i初始值为0,第一行i=!i,则i=1,结果为真,处理,所以上面第一行显示
第二行时,i初始值为1,i=!i,则i=0,结果为假,不处理,所有上面第二行没显示,
下面就是循环赋值了,每到技奇数行i=1,偶数行i=0,所以才有上面的效果
(注意1为真,0为假,非1的结果就是假了,而非0的结果就是真了)
如果我们使得i的初始值为真,那么结果就和上面的相反了,显示的是偶数行
6.常用的action
1.表达式Expressions
2.控制语句Control statements :if while等
3.组合语句Compound statements :组合语句
4.输入语句input statements
5.输出语句outut statements :print等
7.控制语句
if (condition) { statements }
if (condition) { statements } else { statements }
while (condition) { statements }
do { statements } while (condition)
for (expr1;expr2;expr3) { statements }
break
continue
delete array[index]
delete array
exit
{ statements }
awk控制语句if-else
语法:if(condition) statements [ else statements]
if(condition1) {statement1}else if(condition2) {statement2} esle{statement3}
使用场景:对awk取得的整行或某个字段做条件判断
示例:
如果uid大于1000就显示此行中的第1,3列,分隔符为”:“
如果uid大于1000则显示为conmmon user,否则显示system user,并显示第1,3列,分隔符为”:“
说明 90分以下为very good 60-90为good,60分以下为不及格
以/dev开头的行,分隔符为%,取第一列,然后显示的行中默认可个为分隔符,最后一行如果大于20,则显示第1行和最后一行
awk控制语句=====while循环
语法:while(condition){statement}
条件为”真“,进入循环;条件为”假“,退出循环
使用场景:
对一行内的多个字段注意类似处理时使用
对数组中那个的各元素逐一处理时使用
示例:
说明:文件为/etc/grub.cfg,匹配以任意数量的空格开头后面跟Linux16的行,做while循环,初始值i=1,判断题条件为i<NF(每行字段数),
i++自增,打印内容为每行的每个字段,以及此字符个数。默认分隔符为" "
说明:在上面的基础上加了一个判断条件,字段中字符分个数大于等于10,打印内容为每行的每个字段,以及此字符个数。默认分隔符为" "
awk控制语句=====do-while循环
语法:do {statement;…}while(condition)
意义:无论真假,至少执行一次循环
示例:
说明不同:
后面的i没有争议,那么i++和++i的却别就在于,先后顺序,
第一个是先显示i,然后才自增赋值的,所以值为
第二个是先自增赋值,然后才显示i的,所以值为1
awk控制语句===for循环
语法:for(expr1;expr2;expr3){statement;…}
常见用法:
for(variable assignment;condition;iteration process){for-body}
特殊用法:能够遍历数组中的元素;
语法: :for(var in array) {for-body}
示例:
awk '/^[[:space:]]*linux16/{for(i=1;i<=NF;i++) {print $i,length($i)}}' /etc/grub2.cfg
性能比较:
time (awk 'BEGIN{total=0;for(i=0;i<=10000;i++){total+=i;};print total;}')
time(total=0;for i in {1..1000000};do total=$(($total+i));done;echo $total)
time(for ((i=0;i<=1000000;i++));do let total+=i;done;echo $total)
结果很显然是awk运算最快,想想也知道了,这章博客主要内容就是awk,做这个比较肯定想体现akw是有多牛逼咯
awk控制语句====>switch语句
语法:swicth(expression){case VALUE1 or /REGEXP/:statement;case VALUE2 or /REGEXP2/:statement;…;default:statement}
break和continue
示例:
break表示当i=66的时候中断此循环,所以结果是1加到65
continue表示当i为偶数的时候终止了本轮循环,所以结果为奇数相加
break[n]
continue[n]
next:
提前结束对本行处理而直接进入下一轮处理(awk自身循环)
说明:当uid为奇数时,提前结束本行,跳过本行要处理的,
awk数值:array[index-expression]
index-expression:
1.可使用任意字符串;字符串要使用双引号括起来
2.如果某数组元素事先不存在,在引用时,awk会自动创建此元素,并将其值初始化为“空串”
若要判断数组中是否存在某元素,要使用“index in array”格式进行遍历
示例:
awk ‘!a[$0]++’ dupfile
若要遍历数组中的每个元素,要使用for循环
for(var in array) {for-body}
注意:var会遍历array的每个索引
示例:
说明:统计tcp开头的单词中最后一字段出现次数
说明:统计第一段ip出现的次数
awk函数:
rand():返回0和1之一个随机数
[root@localhost ~]# awk 'BEGIN{srand(); for (i=1;i<=10;i++)print int(rand()*100) }'
字符串处理:
length([s]):返回指定字符串的长度
sub(r,s,[t]):对t字符串进行搜索r表示的模式匹配的内容,并将第一个匹配的内容替换成s
echo "2008:08:08 08:08:08" | awk 'sub(/:/,“-",$1)'
gsub(r,s,[t]):对t字符串进行搜索r表示的模式匹配的内容,并全部替换为s所表示的内容
echo "2008:08:08 08:08:08" | awk ‘gsub(/:/,"",$1)'
split(s,array ,[r]):以r为分隔符,切割字符s,并将切割后的结果保存至array所表示的数组中,第一个索引值为1
第二个索引值为2…
自定义函数
格式
function name (parameter,parameter,….){
statements
return exprossion
}
示例:
#!/bin/bash function max(v1,v2) { v1>v2?var=v1:var=v2 return var } BEGIN{a=3;b=2;print max(a,b)}
1 #!/bin/bash 2 function max(v1,v2) { 3 v1>v2?var=v1:var=v2 4 return var 5 } 6 BEGIN{print max(a,b)}
awk中调用shell命令
system命令
空格是awk中的字符串连接符,如果system中需要使用awk中的变量可以使用空格分隔,或者说除了awk
的变量外其他的一律用“”引用起来
awk脚本
将awk程序写成脚本,直接调用或执行
示例:
向awk脚本传递参数
格式:
awkfile var=value var2=value2… Inputfile
[root@localhost bin]# cat test.awk #!/bin/awk -f {if($3<=min||$3>=max)print $1,$3} [root@localhost bin]# test.awk -F: min=10 max=1000 /etc/passwd
练习
1 、 统计/etc/fstab文件中每个文件系统类型出现 的次数
awk '/^UUID/{fs[$3]++}END{for(i in fs) {print i,fs[i]}}' /etc/fstab
2、 、 统计/etc/fstab 文件中每个单词出现的次数
[root@localhost bin]# awk '{for(i=1;i<=NF;i++){count[$i]++}}END{for(i in count) {print i,count[i]}}' /etc/fstab man 1 and/or 1 /mnt 1 maintained 1 xfs 4 14:09:19 1 UUID=b39702a5-31f8-4fca-96cc-3389a0a58059 1 Accessible 1 # 7 are 1 defaults 5 blkid(8) 1 / 1 0 13 See 1 3 1 Mon 1 Created 1 on 1 usrquota,grpquota 1 mount(8) 1 ext4 2 acl 1 anaconda 1 fstab(5), 1 /boot 1 /testdir 1 /usr 1 UUID=bd915a87-493a-415b-8d2f-8cedaab84792 1 findfs(8), 1 2016 1 /home 1 '/dev/disk' 1 UUID=5bc0405e-cf7a-4d60-8c0c-a6daa1dd71d2 1 by 2 /etc/fstab 1 UUID=12294f2d-4b7d-4f64-a8b7-1522fe51d0b2 1 pages 1 UUID=d8150c22-3804-4d3e-bd18-8f44e93bb978 1 more 1 25 1 info 1 UUID=8d687919-88d4-4c2a-9e0b-473cd13bb785 1 swap 2 Jul 1 UUID=14efdeb1-9880-49dc-aaa0-321c4eb4816a 1 filesystems, 1 reference, 1 for 1 under 1
原创文章,作者:qiuwei,如若转载,请注明出处:http://www.178linux.com/47950