Shell基础之-awk命令

Shell基础之-awk命令

首先,大家如果看到有什么不懂的地方,欢迎吐槽!!!
我会在当天或者第二天及时回复,并且改进~~


awk编程
awk是一种编程语言。gawk、是最新版本,当前的linux版本用的都是gawk
awk是gawk的软链接

awk工作原理

   BEGIN   #在未读取文件行之前执行
   主输入循环 (main input loop),反复执行,直到终止条件触发
   END     #在读取文件行完毕后执行
1、在shell命令行输入命令调用awk
   #awk [-f 域分隔符] 'awk cmd' file

2、在awk程序段插入脚本文件,然后通过awk命令调用他
   #awk -f 'awk.sh' file

3、直接调用awk脚本
   #./awk file

awk模式匹配

任何awk语句都由模式(pattern)和动作(action)组成
    模式是一组用于测试输入行是否需要执行动作的规则(模式决定动作何时触发和触发事件)
    动作是包含语句、函数和表达式的执行过程  (执行对输入行的处理)

在test文件中一旦有空行,则打印出来"This is a empty line!!!"
    awk '/^$/{print "This is a empty line!!!"}' test

记录和域

awk将每个输入文件行定义为记录,行中的每个字符串定义为域,分隔域的符号叫做域分隔符

Li Hao  njue    025-83481010
Zhang Ju    nju 025-83466534
Wang Bin    seu 025-83494883
Zhu Lin njupt   025-83680010

按顺序打印出student文件中的2143域
   awk '{print $2,$1,$4,$3}' student
打印出student中所有的域
   awk '{print $0}' student
根据运算表达式列出第三个域的值
   awk 'BEGIN {one=1;two=2}{print $(one+two)}' student
以tab键位分隔符打印出student文件中第三个域
   awk 'BEGIN {FS="\t"} {print $3}' student
Li Hao,njue,025-83481010
Zhang Ju,nju,025-83466534
Wang Bin,seu,025-83494883
Zhu Lin,njupt,025-83680010

以逗号为域分隔符打印出所有的域的内容
   awk 'BEGIN {FS=","} {print $0}' student
以逗号为域分隔符打印出13域的内容
   awk 'BEGIN {FS=","} {print $1,$3}' student

abc     d   #中间两个tab
abc d       #中间一个tab

打印出第一个域和d(两种方式)
   awk 'BEGIN {FS="\t\t"} {print $1,$2}' xx
   awk 'BEGIN {FS="\t"} {print $1,$3}' xx

打印出第一个域和上面的d
   awk 'BEGIN {FS="\t"} {print $1,$2}' xx

关系运算符

<       #小于
>       #大于
<=      #小于等于
>=      #大于等于
==      #等于
!=      #不等于
~      #匹配正则表达式
!~     #不匹配正则表达式
在/etc/passwd文件中打印出第一个域匹配于root的内容
   awk 'BEGIN {FS=":"} $1~/root/' /etc/passwd 
在/etc/passwd文件中打印出全部域匹配于root的内容
   awk 'BEGIN {FS=":"} $0~/root/' /etc/passwd
在/etc/passwd文件中打印出全部域中不匹配nologin的内容
   awk 'BEGIN {FS=":"} $0!~/nologin/' /etc/passwd
在/etc/passwd文件中判断,如果UID小于GID,那么输出所有匹配的值
   awk 'BEGIN {FS=":"} {if($3<$4) print $0}' /etc/passwd
在/etc/passwd文件中判断,如果UID大于等于GID,那么输出所有匹配的值
   awk 'BEGIN {FS=":"} {if($3>=$4) print $0}' /etc/passwd

布尔运算符

||  #逻辑或
&&  #逻辑与
!   #逻辑非

打印出/etc/passwd文件中UID等于10或者GID等于10的行
   awk 'BEGIN {FS=":"} {if($3==10||$4==10) print $0}' /etc/passwd

打印出/etc/passwd文件中UID等于GID,并且登录shell都相同的匹配信息
   awk 'BEGIN {FS=":"} {OFS=":"} {if($3==$4&&$7="/sbin/nologin") print $0}' /etc/passwd

打印出/etc/passwd文件中UID匹配于10或GID匹配于10的匹配信息
   awk 'BEGIN {FS=":"} {if($3~10||$4~10) print $0}' /etc/passwd

表达式 awk表达式用于存储、操作和获取数据,一个awk表达式可由数值,字符常量,变量,操作符,函数和正则组成

+       #加
-       #减
*       #乘
/       #除
%       #模
^或**    #乘方
++x #在返回x值之前,x变量加1
x++ #在返回x值之后,x变量加1

使用x+=1来列出文件test中的空行的行数
   awk '/^$/ {print x+=1}' test
第1行为0,然后递归+1列出test文件中的空行行数
   awk '/^$/{print x++}' test
第1行为1,然后递归+1列出test文件中的空行行数
   awk '/^$/{print ++x}' test
Li     hao,njue,025-83481010,85,92,78,94,88
Zhang  Ju,nju ,025-83466534,89,90,75,90,86
Wang   Bin, seu,025-83494883,84,88,80,92,84
Zhu    Lin,njupt,025-83680010,98,78,81,87,76

求出文件student文件中学生的平均值
   #awk 'BEGIN {FS=","} {total=$4+$5+$6+$7+$8} {avg=total/5} {print $1,avg}' student

系统变量:awk定义了很多内建变量用于设置环境变量信息,我们称它为系统变量,这些系统变量分为两种

   1、用于改变awk的默认值,如域分隔符
   2、用于定义系统值,在处理文件时可以读取这些系统值,如记录中域数量,当前记录数,当前文件名,awk动态改变第二种系统变量的值

awk环境变量及其意义

#n          #当前记录的第n个域,域间由FS分割
#0          #记录的所有域
ARGC        #命令行参数的数量
ARGIND      #命令行中当前文件的位置(以0开始标号)
ARGV        #命令行参数的数组
CONVFMT     #数字转换格式
ENVIRON     #环境变量关联数组
ERRNO       #最后一个系统错误的描述
FILEDWIDTHS #字段宽度列表,以空格键分隔
FILENAME    #当前文件名
FNR         #浏览文件的记录数
FS          #字段分隔符,默认是空格键
IGONRECASE  #布尔变量,如果为真,则进行忽略大小写的匹配
NF          #当前记录中的域数量
NR          #当前记录数
OFMT        #数字的输出格式
OFS         #输出域分隔符,默认是空格键
ORS         #输出记录分隔符,默认是换行符
RLENGTH     #由match函数所匹配的字符串长度
RS          #记录分隔符,默认是空格键
RSTART      #由match函数所匹配的字符串的第1个位置
SUBSEP      #数组下标分隔符,默认值是\034

输出文件student,并在最前面加入 当前记录数,当前记录中域数量,在文件底部输出文件名
   awk 'BEGIN {FS=","} {print NR,NF,$0} END {print FILENAME}' student

格式化输出 awk借鉴了C语言的语法,定义了printf输出语句,规定输出的格式

    printf (格式控制符,参数)

printf语句包含两部分

   1、格式控制符,都是以%符号开始,用以描述格式规范
   2、参数列表,比如变量名列表,与格式控制符相对应,是输出的对象、

printf修饰符及其意义

    -   #左对齐
width   #域的步长
.prec   #小数点右边的位数

printf格式符及其意义

%c  #ASCII字符
%d  #整型数
%e  #浮点数,科学记数法
%f  #浮点数
%o  #八进制
%s  #字符串
%x  #十六进制数

示例:

在student中打印出字符串$2和整型数$8,并且$2之后tab,$8之后换行
   awk 'BEGIN {FS=","} {printf("%s\t%d\n",$2,$8)}' student

将数字65转换为ASCII码
   awk 'BEGIN {printf("%c\n",65)}'

将2014转换为浮点数,默认小数位六位
   awk 'BEGIN {printf("%f\n",2014)}'

打印出student文件中的第一个域和第三个域,并且第一个域的字符串和第三个域的字符串相差15个空格   
   awk 'BEGIN {FS=","} {printf("%-15s\t%s\n",$1,$3)}' student

打印出student文件中的第一个域和第三个域,并且在行首加入第一个域的注释Name,第三个域的注释Phonenumber
   awk 'BEGIN {FS=",";print "Name\t\tPhonenumber"} {printf("%-16s%s\n",$1,$3)}' student 

打印出浮点数控制在10为,小数点后保留三位的数
   awk 'BEGIN {printf("%10.3f\n",20141126)}'  #如果数不满10位,则会按

空格补齐
   2011111.000  满10位  
   201.000      不满10位

内置字符串函数 awk提供了强大的内置字符串函数,用于实现文本的字符串替换、查找以及分隔等功能

awk字符串函数及其意义

gsub(r,s)       #在输入文件中用s替换r
gsub(r,s,t)     #在t中用s替换r
index(s,t)      #返回s中字符串第一个t的位置
length(s)       #返回s的长度
match(s,t)      #测试s是否包含匹配t的字符串
split(r,s,t)    #在t上将r分成序列s
sub(r,t,s)      #将t中第1次出现的r替换为s
substr(r,s)     #返回字符串r中从s开始的后缀部分
substr(r,s,t)   #返回字符串r中从s开始长度为t的后缀部分

示例:

在passwd中把第一个域的root替换为"My name is root",并输出为:格式打印出来
   awk 'BEGIN {FS=":";OFS=":"} gsub(/root/,"my name is root",$1) {print $0}' /etc/passwd 

在passwd中把所有域的root替换为"My name is root",并输出为:格式打印出来

打印出abcdefg字符串中f出现的首位置
   awk 'BEGIN {print index("abcdefg","f")}'

打印出"This is a httpd server script"这串字符串的长度
   awk 'BEGIN {print length("This is a httpd server script")}'

测试"This is a httpd server script!!!"这串字符串中!的首位置
   awk 'BEGIN {print match("This is a httpd server sctipt!!!","!")}'

测试"This is a httpd server sctipt!!!"这串字符串中C的首位置(忽略大小写)
   awk 'BEGIN {IGNORECASE=1;print match("This is a httpd server sctipt!!!",/C/)}'

将字符串"This script is a httpd server script!!!"中第一个出现的sctipt替换为SCRIPT
   awk 'BEGIN {file="This script is a httpd server script!!!";sub(/script/,"SCRIPT",file);printf("%s\n",file)}'

将student文本中第一个域匹配Li行中的第一个出现的10替换为99
   awk 'BEGIN {FS=","} {$1~Li sub(/10/,"99",$0);print $0}' student

返回file文件中从第5个字符开始的后缀部分 file="This script is a httpd server script!!!"
   awk 'BEGIN {file="This script is a httpd server script!!!";print substr(file,6)}'

返回file文件中从第6个字符开始长度为9的后缀部分
   awk 'BEGIN {file="This script is a httpd server script!!!";print substr(file,6,9)}'

在student文件记录首部插入记录行号和域数,并且使用分隔符.进行分隔打印
   awk 'BEGIN {FS=","} {print NR,NF,$0}' OFS="." student            
上一篇:Shell基础之-正则表达式


下一篇:Shell基础之-变量、比较、测试