简述awk命令及用法
AWK是一种处理文本文件的语言,是一个强大的文本分析工具。
语法
awk [options]'program' {filenames}
参数
-F:指明输入时用到的字段分隔符,默认是空格符
-v var=value: 自定义变量
program
program: PATTERN{ACTION STATEMENTS}
语句之间用分号分隔
- print
- 格式 :print item1,item2,….
$0:表示整个当前行 $1:每行第一个字段 NR:number of record, 总行数; NF:number of field,字段数量 {print NF}:打印每行的字段 {print $NF}:打印第NF个字段值(最后一个字段的值) FNR:单个数据文件处理的行数 \t:制表符 \n:换行符
- 实例
- F & $0
#输出整行,awk {print} /etc/passwd = awk '{print $0}' /etc/passwd~]# awk {print} /etc/passwd~]# awk '{print $0}' /etc/passwdroot:x:0:0:root:/root:/bin/bashbin:x:1:1:bin:/bin:/sbin/nologindaemon:x:2:2:daemon:/sbin:/sbin/nologin#":"为分格符输出第一个字符~]# awk -F":" '{print $1}' /etc/passwdrootbindaemon#$1与$3相连输出,不分隔~]# awk -F":" '{print $1 $3}' /etc/passwd root0bin1daemon2#多了一个逗号,$1与$3使用空白分格分隔~]# awk -F":" '{print $1,$3}' /etc/passwdroot 0bin 1daemon 2#$1与$3使用分格符分隔,自定义分隔符~]# awk -F":" '{print $1 "," $3}' /etc/passwdroot,0bin,1daemon,2 ~]# awk -F":" '{print $1 "-" $3}' /etc/passwdroot-0bin-1daemon-2 #自定义输出内容~]# awk -F":" '{print "Username:" $1" \t Uid:" $3 }' /etc/passwdUsername:root Uid:0Username:bin Uid:1
- NF
#显示每行有多少字段~]# awk -F: '{print NF}' /etc/passwd 777#将每行第NF个字段的值打印出来 ~]# awk -F: '{print $NF}' /etc/passwd/bin/bash/sbin/nologin/sbin/nologin#只输出字段数=7的行~]# awk -F":" 'NF==7 {print }' /etc/passwdroot:x:0:0:root:/root:/bin/bashbin:x:1:1:bin:/bin:/sbin/nologindaemon:x:2:2:daemon:/sbin:/sbin/nologin#输出字段数>2的行~]# awk -F":" 'NF>2{print $0}' /etc/passwdroot:x:0:0:root:/root:/bin/bashbin:x:1:1:bin:/bin:/sbin/nologindaemon:x:2:2:daemon:/sbin:/sbin/nologin
- NR
#输出每行的行号localhost ~]# awk '{print NR,$0}' /etc/passwd 1 root:x:0:0:root:/root:/bin/bash2 bin:x:1:1:bin:/bin:/sbin/nologin3 daemon:x:2:2:daemon:/sbin:/sbin/nologin#显示第5行localhost ~]# awk -F: 'NR==5{print}' /etc/passwd lp:x:4:7:lp:/var/spool/lpd:/sbin/nologin#显示5行以后的数据,并在前面显示行号localhost ~]# awk -F: 'NR>5{print NR ,$0}' /etc/passwd 6 sync:x:5:0:sync:/sbin:/bin/sync7 shutdown:x:6:0:shutdown:/sbin:/sbin/shutdown8 halt:x:7:0:halt:/sbin:/sbin/halt.....#显示5行和第8行,并在前面显示行号localhost ~]#awk -F: 'NR==5 || NR == 8 {print NR ,$0}' /etc/passwd 5 lp:x:4:7:lp:/var/spool/lpd:/sbin/nologin8 halt:x:7:0:halt:/sbin:/sbin/halt
- FNR&NR
localhost tmp]# cat data3hellohellohellolocalhost tmp]# awk '{print $0 ,"\t""FNR="FNR,"NR="NR}' data3 data3hello FNR=1 NR=1hello FNR=2 NR=2hello FNR=3 NR=3hello FNR=1 NR=4hello FNR=2 NR=5hello FNR=3 NR=6
- F & $0
- 格式 :print item1,item2,….
- 格式化打印printf
printf FORMAT, item1, item2, ... (1) FORMAT必须给出; (2) 不会自动换行,需要显式给出换行控制符,\n (3) FORMAT中需要分别为后面的每个item指定一个格式化符号;
- 格式符:
%c: 显示字符的ASCII码;%d, %i: 显示十进制整数;%e, %E: 科学计数法数值显示;%f:显示为浮点数;%g, %G:以科学计数法或浮点形式显示数值;%s:显示字符串;%u:无符号整数;%%: 显示%自身;
- 修饰符
#[.#]:第一个数字控制显示的宽度;第二个#表示小数点后的精度;-: 左对齐+:显示数值的符号
- 说明
(1). 可以在"%"和字母之间插进数字表示最大场宽。 例如:%3d 表示输出3位整型数, 不够3位右对齐。 %9.2f 表示输出场宽为9的浮点数, 其中小数位为2, 整数位为6,小数点占一位, 不够9位右对齐。 %8s 表示输出8个字符的字符串, 不够8个字符右对齐。 如果字符串的长度、或整型数位数超过说明的场宽, 将按其实际长度输出.但对浮点数, 若整数部分位数超过了说明的整数位宽度, 将按实际整数位输出;若小数部分位数超过了说明的小数位宽度, 则按说明的宽度以四舍五入输出.另外, 若想在输出值前加一些0, 就应在场宽项前加个0。 例如: %04d 表示在输出一个小于4位的数值时, 将在前面补0使其总宽度为4位。 如果用浮点数表示字符或整型量的输出格式, 小数点后的数字代表最大宽度,小数点前的数字代表最小宽度。 例如: %6.9s 表示显示一个长度不小于6且不大于9的字符串。若大于9, 则第9个字符以后的内容将被删除。(2). 可以在"%"和字母之间加小写字母l, 表示输出的是长型数。 例如: %ld 表示输出long整数 %lf 表示输出double浮点数 (3). 可以控制输出左对齐或右对齐, 即在"%"和字母之间加入一个"-" 号可说明输出为左对齐, 否则为右对齐。 例如: %-7d 表示输出7位整数左对齐 %-10s 表示输出10个字符左对齐
- 实例
#%d 显示十进制整数~]# echo "1.7 2.52" | awk '{printf ("%d\n",$2)}'2#%f 显示浮点数 ~]# echo "1.7 2.52" | awk '{printf ("%f\n",$1)}'1.700000#四舍五入输入整数~]# echo "1.5" | awk '{printf ("%.f\n",$1)}' 2echo "1.4" | awk '{printf ("%.f\n",$1)}' 1#以3位长度、1位小数,"."占一位,浮点换行输出第2个域(四舍五入)~]# echo "1.7 2.52" | awk '{printf ("%3.1f\n",$2)}'2.5#以6位长度,其中整数占2位,不足2位空格补足,“.”占一位,小数占3位,不足3位用0补足~]# echo "1.7 2.52" | awk '{printf ("%6.3f\n",$2)}'2.520#指数形式的浮点数输出~]# echo "1.7 2.52" | awk '{printf ("%e\n",$1)}'1.700000e+00#用0补充格式~]# echo "123 1" | awk '{printf("%d\t%03d\n",$1,$2)}'123 001
- 格式符:
- BEGIN/END模式
BEGIN{}: 仅在开始处理文件中的文本之前执行一次;END{}:仅在文本处理完成之后执行一次;
- 实例
#开头显示“The data of passwd”localhost ~]# awk 'BEGIN{print "The data of passwd"} {print}' /etc/passwdThe data of passwdroot:x:0:0:root:/root:/bin/bashbin:x:1:1:bin:/bin:/sbin/nologindaemon:x:2:2:daemon:/sbin:/sbin/nologin#显示第一行,并在开头和末尾显示“The data of passwd”localhost ~]# awk 'BEGIN{print "print /etc/passwd"} NR==1{print} END{print "print /etc/passwd"}' /etc/passwdprint /etc/passwdroot:x:0:0:root:/root:/bin/bashprint /etc/passwd
- 实例
- 使用变量
- 内建变量:字段和记录分隔符变量
FS:input field seperator,输入字段分隔符,默认为空白字符OFS:output field seperator,输出字段分隔符, 默认空白字符;RS:input record seperator,输入时的换行符;ORS:output record seperator,输出时的换行符;FIELDWIDTHS:指定列
- 实例
- FS&OFS
#自定义分输入隔符为“:”localhost ~]#awk 'BEGIN{FS=":"} NR<4{print $1,$2,$3}' /etc/passwdroot x 0bin x 1daemon x 2#自定义分输入隔符为“:”,输出分隔符为“-”localhost ~]# awk 'BEGIN{FS=":" ;OFS="-"} NR<4{print $1,$2,$3}' /etc/passwdroot-x-0bin-x-1daemon-x-2
- RS&ORS
#输入时以回车符为分隔符,空白行为换行符,localhost tmp]# cat data2Riley Mullen123 Main StreetChicago, IL 60601(312)555-1234Frank Williams456 Oak StreetIndianapolis, IN 46201(317)555-9876Haley Snell4231 Elm StreetDetroit, MI(313)555-4938localhost tmp]# awk 'BEGIN{FS="\n"; RS=""}{print $1 ,$4}' data2Riley Mullen (312)555-1234Frank Williams (317)555-9876Haley Snell (313)555-4938
- FIELDWIDTHS
#以特定列为分隔localhost tmp]# cat data11005.3247596.37115-2.349194.0005810.1298100.1localhost tmp]# awk 'BEGIN{FIELDWIDTHS="3 5 2 5"} {print $1,$2,$3,$4}' data1100 5.324 75 96.37115 -2.34 91 94.00058 10.12 98 100.1
- 自定义变量
- 在脚本中给变量复制
变量名可以是任意数目的字母、数字和下划线,但不能以数字开头
- 实例
localhost ~]#awk 'BEGIN{test="hello everyone";print test}'hello everyonelocalhost ~]# awk 'BEGIN{x=4;x=x*2+3;print x}'11
- 实例
- 在命令行上给变量复制
localhost tmp]# cat data4data11 data12 data13data21 data22 data23data31 data32 data33localhost tmp]# cat script1BEGIN{print "The starting value is",n}{print $n}localhost tmp]# awk -v n=3 -f script1 data4The starting value is 3data13data23data33
- 在脚本中给变量复制
- 内建变量:字段和记录分隔符变量
- 数组变量
var[index] = elementvar:变量名index:索引值element:数据元素值
- 遍历数组变量
for (var in array){ statements}
for语句在每次循环时将关联数组array下一个索引值赋给变量var,然后执行一遍statements
- 实例
localhost ~]# awk 'BEGIN{var["a"] =1;var["b"]=2;var["c"]=3;var["d"]=4;for (i in var) {print var[i]}}' 1 2 3 4 #统计IP链接数 localhost ~]# awk '{ip[$1]++}END{for(i in ip) {print i,ip[i]}}' /var/log/httpd/access_log 192.168.1.48 10 #统计tcp链接状态和数量,IPV4 localhost ~]# netstat -tan | awk '/^tcp\>/{state[$NF]++}END{for(i in state) { print i,state[i]}}' LISTEN 2 ESTABLISHED 3 #统计/etc/fstab文件中每个文件系统类型出现的次数 localhost ~]# awk '/^UUID/{fs[$3]++}END{for(i in fs) {print i,fs[i]}}' /etc/fstab xfs 1 #统计指定文件中每个单词出现的次数; localhost ~]# awk '{for(i=1;i<=NF;i++){count[$i]++}}END{for(i in count) {print i,count[i]}}' /etc/fstab
- 实例
- 遍历数组变量
- 字符串匹配
// 纯字符匹配 !// 纯字符不匹配 ~// 字段值匹配 !~// 字段值不匹配 ~/a1|a2/ 字段值匹配a1或a2
- 实例
#显示mysql相关信息 localhost ~]# awk '/mysql/{print $0}' /etc/passwd mysql:x:27:27:MariaDB Server:/var/lib/mysql:/sbin/nologin #显示非mysql localhost ~]# awk '!/mysql/{print $0}' /etc/passwd #显示mail和mysql localhost ~]# awk '/mail|mysql/{print $0}' /etc/passwd mail:x:8:12:mail:/var/spool/mail:/sbin/nologin mysql:x:27:27:MariaDB Server:/var/lib/mysql:/sbin/nologin #显示$1匹配mail localhost ~]# awk -F: '$1~/mail/{print $1}' /etc/passwd mail
- 实例
- 操作符
- 算数操作符
x+y: 加 x-y:减 x*y:乘 x/y:除 x^y:次方 x%y:余数
- 赋值操作符
= : x=y +=: x+=5 (x=x+5) -=: x-=5 (x=x-5) /=: x/=5 (x=x/5) %=: x%=5 (x=x%5) ^=: x^=5 (x=x^5) ++: x++ (x=x+1) --: x-- (x=x-1)
- 比较操作符
> >= < <= != ==
- 模式匹配符
~:是否匹配 !~:是否不匹配
- 逻辑操作符:
&& || !
- 条件表达式
selector?if-true-expression:if-false-expression 实例: ~]# awk -F: '{$3>=1000?usertype="Common User":usertype="Sysadmin or SysUser";printf "%15s:%-s\n",$1,usertype}' /etc/passwd root:Sysadmin or SysUser bin:Sysadmin or SysUser daemon:Sysadmin or SysUser adm:Sysadmin or SysUser lp:Sysadmin or SysUser sync:Sysadmin or SysUser
- 算数操作符
- 控制语句
- if语句
if(condition) {statments} if(condition) {statments} else {statements}
实例:
#简单的if语句 ~]# awk -F: '{if($NF=="/bin/bash") print $1}' /etc/passwd root centos test linux testuser #if-else语句 ~]# awk -F: '{if($3>=1000) {printf "Common user: %s\n",$1} else {printf "root or Sysuser: %s\n",$1}}' /etc/passwd ~]#awk -F: '{if($3>=1000) printf "Common user: %s\n",$1; else printf "root or Sysuser: %s\n",$1}' /etc/passwd root or Sysuser: root root or Sysuser: bin root or Sysuser: daemon root or Sysuser: adm root or Sysuser: lp #在if中执行多条语句和if-else语句 [root@localhost tmp]# cat data1 10 5 13 50 34 [root@localhost tmp]# awk '{if ($1>20) {x= $1*2; print $1,x}}' data1 50 100 34 68 ~]# awk '{if($1>20) print $1*2;else print $1/2}' data1 5 2.5 6.5 100 68 #打印磁盘使用率超过10%的 ~]# df -h | awk -F[%] '/^\/dev/{print $1}' | awk '{if($NF>=10) print $1}' /dev/mapper/cl-root /dev/sda1
- while循环
while(conditon) {statments} 条件“真”,进入循环;条件“假”,退出循环
实例:对一行内的多个字段逐一类似处理时使用;对数组中的各元素逐一处理时使用
~]# awk '/^[[:space:]]*linux16/{i=1;while(i<=NF) {print $i,length($i); i++}}' /etc/grub2.cfg linux16 7 /vmlinuz-3.10.0-514.el7.x86_64 30 root=/dev/mapper/cl-root 24 ro 2 crashkernel=auto 16 rd.lvm.lv=cl/root 17 rd.lvm.lv=cl/swap 17 rhgb 4 quiet 5 LANG=en_US.UTF-8 16 linux16 7 /vmlinuz-0-rescue-071d709683fd4359a4845645d1906b29 50 root=/dev/mapper/cl-root 24 ro 2 crashkernel=auto 16 rd.lvm.lv=cl/root 17 rd.lvm.lv=cl/swap 17 rhgb 4 quiet 5 ~]# awk '/^[[:space:]]*linux16/{i=1;while(i<=NF) {if(length($i)>=7) {print $i,length($i)}; i++}}' /etc/grub2.cfg linux16 7 /vmlinuz-3.10.0-514.el7.x86_64 30 root=/dev/mapper/cl-root 24 crashkernel=auto 16 rd.lvm.lv=cl/root 17 rd.lvm.lv=cl/swap 17 LANG=en_US.UTF-8 16 linux16 7 /vmlinuz-0-rescue-071d709683fd4359a4845645d1906b29 50 root=/dev/mapper/cl-root 24 crashkernel=auto 16 rd.lvm.lv=cl/root 17 rd.lvm.lv=cl/swap 17
- do-while循环
至少执行一次循环体
- for循环
for(expr1;expr2;expr3) {statements}
实例
~]# awk '/^[[:space:]]*linux16/{for(i=1;i<=NF;i++) {print $i,length($i)}}' /etc/grub2.cfg linux16 7 /vmlinuz-3.10.0-514.el7.x86_64 30 root=/dev/mapper/cl-root 24 ro 2 crashkernel=auto 16 rd.lvm.lv=cl/root 17 rd.lvm.lv=cl/swap 17 rhgb 4 quiet 5 LANG=en_US.UTF-8 16 linux16 7 /vmlinuz-0-rescue-071d709683fd4359a4845645d1906b29 50 root=/dev/mapper/cl-root 24 ro 2 crashkernel=auto 16 rd.lvm.lv=cl/root 17 rd.lvm.lv=cl/swap 17 rhgb 4 quiet 5
- if语句
- 内建函数
- 数学函数
atan2(x, y) x/y的反正切,x和y以弧度为单位 cos(x) x的余弦,x以弧度为单位 exp(x) x的指数函数 int(x) x的整数部分,取靠近零一侧的值 log(x) x的自然对数 rand( ) 比0大比1小的随机浮点值 sin(x) x的正弦,x以弧度为单位 sqrt(x) x的平方根 srand(x) 为计算随机数指定一个种子值
- 字符串函数
asort(s [,d]) 将数组s按数据元素值排序。索引值会被替换成表示新的排序顺序的连续数字。另外,如果指定了d,则排序后的数组会存储在数组d中 asorti(s [,d]) 将数组s按索引值排序。生成的数组会将索引值作为数据元素值,用连续数字索引来表明排序顺序。另外如果指定了d,排序后的数组会存储在数组d中 gensub(r, s, h [, t]) 查找变量$0或目标字符串t(如果提供了的话)来匹配正则表达式r。如果h是一个以g或G开头的字符串,就用s替换掉匹配的文本。如果h是一个数字,它表示要替换掉第h处r匹配的地方 gsub(r, s [,t]) 查找变量$0或目标字符串t(如果提供了的话)来匹配正则表达式r。如果找到了,就全部替换成字符串s index(s, t) 返回字符串t在字符串s中的索引值,如果没找到的话返回0 length([s]) 返回字符串s的长度;如果没有指定的话,返回$0的长度 match(s, r [,a]) 返回字符串s中正则表达式r出现位置的索引。如果指定了数组a,它会存储s中匹配正则表达式的那部分 split(s, a [,r]) 将s用FS字符或正则表达式r(如果指定了的话)分开放到数组a中。返回字段的总数 sprintf(format,variables) 用提供的format和variables返回一个类似于printf输出的字符串 sub(r, s [,t]) 在变量$0或目标字符串t中查找正则表达式r的匹配。如果找到了,就用字符串s替换掉第一处匹配 substr(s, i [,n]) 返回s中从索引值i开始的n个字符组成的子字符串。如果未提供n,则返回s剩下的部分 tolower(s) 将s中的所有字符转换成小写 toupper(s) 将s中的所有字符转换成大写
- 时间函数
mktime(datespec) 将一个按YYYY MM DD HH MM SS [DST]格式指定的日期转换成时间戳值① strftime(format[,timestamp])将当前时间的时间戳或timestamp(如果提供了的话)转化格式化日期(采用shell函数date()的格式) systime( ) 返回当前时间的时间戳
- 数学函数
本文来自投稿,不代表Linux运维部落立场,如若转载,请注明出处:http://www.178linux.com/101093