awk [options] 'scripts' file1,file2...
awk [options] 'pattern {action}' file1,file2...
- [root@mos download]# cat demo.txt
- Welcome to mos blog.
- This is a test file.
例:打印整行: $0
- [root@mos download]# awk '{print $0}' demo.txt
- Welcome to mos blog.
- This is a test file.
- [root@mos download]# awk '{print $NF}' demo.txt
- blog.
- file.
- [root@mos download]# awk '{print $2}' demo.txt
- to
- is
- [root@mos download]# awk '{print $(NF-1),"OK"}' demo.txt
- mos OK
- test OK
- [root@mos download]# awk '{print NR,$0}' demo.txt
- 1 Welcome to mos blog.
- 2 This is a test file.
- [root@mos download]# awk '{print ENVIRON["USER"];}' demo.txt
- root
- root
- [root@mos download]# awk 'BEGIN{print ENVIRON["PATH"];}'
- /usr/kerberos/sbin:/usr/kerberos/bin:/usr/local/sbin:/usr/local/bin:/sbin:/bin:/usr/sbin:/usr/bin:/root/bin
- PS:后面的文件只是为了让print成功执行,BEGIN是执行前可以输出的数据,常用作写为报告标题和测试输出,其内容不能获得与文件修改操作有关的变量,后面会说到;
- [root@mos download]# awk -F: {'print $1,$NF'} /etc/passwd|tail -1
- mos1 /bin/bash
- [root@mos download]# awk -v FS=: '{print $1,$NF}' /etc/passwd|head -1
- root /bin/bash
- [root@mos download]# awk -v OFS=. '{print $1,$NF}' demo.txt
- Welcome.blog.
- This.file.
- [root@mos download]# awk -v OFS="~" '{print $1,$NF}' demo.txt
- Welcome~blog.
- This~file.
- [root@mos download]# awk -v OFS=\" '{print $1,$NF}' demo.txt
- Welcome"blog.
- This"file.
- [root@mos download]# awk -v OFS=9 '{print $1,$NF}' demo.txt
- Welcome9blog.
- This9file.
- [root@mos download]# awk -v OFS=XXXX '{print $1,$NF}' demo.txt
- WelcomeXXXXblog.
- ThisXXXXfile.
- PS: 若在print输出字段的之间不写逗号,则输出分隔符无效,输出的结果会直接连在一起
- 属性 说明
- $0 当前记录(作为单个变量)
- $1~$n 当前记录的第n个字段,字段间由FS分隔
- FS 输入字段分隔符 默认是空格
- NF 当前记录中的字段个数,就是有多少列
- NR 已经读出的记录数,就是行号,从1开始
- RS 输入的记录他隔符默 认为换行符
- OFS 输出字段分隔符 默认也是空格
- ORS 输出的记录分隔符,默认为换行符
- ARGC 命令行参数个数
- ARGV 命令行参数数组
- FILENAME 当前输入文件的名字
- IGNORECASE 如果为真,则进行忽略大小写的匹配
- ARGIND 当前被处理文件的ARGV标志符
- CONVFMT 数字转换格式 %.6g
- ENVIRON UNIX环境变量
- ERRNO UNIX系统错误消息
- FIELDWIDTHS 输入字段宽度的空白分隔字符串
- FNR 当前记录数
- OFMT 数字的输出格式 %.6g
- RSTART 被匹配函数匹配的字符串首
- RLENGTH 被匹配函数匹配的字符串长度
- SUBSEP \034
- 声明一下:由于许多变量笔者亦不怎么常用,因此笔者此处未全部列出。
printf format1,format2..., item1,item2...
PS:与print不同的是,首先,其多了个f;然后,其不会自动换行,而且还需要对每个字段指定输出格式。听起来很麻烦,用起来很爽的。
- [root@mos download]# awk '{printf "%15s->%10s\n",$1,$NF}' demo.txt
- Welcome-> blog.
- This-> file.
- [root@mos download]# awk '{printf "%-15s#%10s\n",$1,$NF}' demo.txt
- Welcome # blog.
- This # file.
- [root@mos download]# awk '{printf "%-15s'\''%10s\n",$1,$NF}' demo.txt
- Welcome ' blog.
- This ' file.
- PS:一个单引号的写法太贱了,还有%,得写三个..各种无力吐槽
- [root@mos download]# awk -F: '{printf "%-15s->%10s ->%20s\n",$1,$(NF-3),$NF}' /etc/passwd|head -2
- root -> 0 -> /bin/bash
- bin -> 1 -> /sbin/nologin
- [root@mos ~]# awk 'BEGIN{n1=111.29;n2=-3.444;n3=5.6789;printf("%.2f,%.2u,%.2g,%X,%o\n",n1,n2,n3,n1,n1);}'
- 111.29,18446744073709551613,5.7,6F,157
- 格式符 说明
- %d 十进制有符号整数
- %u 十进制无符号整数
- %f 浮点数
- %s 字符串
- %c 显示字符的ASCII码
- %p 指针的值
- %e 科学技术法显示数值
- %x %X 无符号以十六进制表示的整数
- %o 无符号以八进制表示的整数
- %g %G 以科学计数法或浮点数的格式显示数值
- %% 显示其自身
- 修饰符:
- -: 左对齐 这个好使,下面俩试了试,笔者没试出啥感觉..
- +: 显示数值符号
- N: 显示
awk的输出结果可以直接使用输出重定向和管道,其作用和命令结束再次使用重定向和管道的效果类似,笔者在此不长篇叙述,仅作简单示范和介绍:
print items > output_file
print items >> output_file
print items | command
特殊文件描述符:
/dev/stdin: 标准输入
/dev/sdtout: 标准输出
/dev/stderr: 错误输出
/dev/fd/N: 某特定文件描述符,如/dev/stdin就相当于/dev/fd/0;
- # awk -F: '{printf "%-15s->%+10s->%20s\n",$1,$(NF-2),$NF > "test.txt" }' /etc/passwd
- # awk -F: '{printf "%-15s->%+10s->%20s\n",$1,$(NF-2),$NF }' /etc/passwd > test1.txt
一、算数操作符
- 操作符 描述
- -x 负值
- +x 转换为数值
- x^y 次方
- x**y 次方
- x*y 乘法
- x/y 除法
- x+y 加法
- x-y 减法
- x%y 取余
直接将print输出的结果之间不适用逗号或自定义OFS,即可,其实这是一个空值
例如:以下两例效果一样
- [root@mos download]# awk '{print $1 $2}' demo.txt
- Welcometo
- Thisis
- [root@mos download]# awk '{print $1$2}' demo.txt
- Welcometo
- Thisis
- 操作符 描述
- = 赋值操作符
- += 赋值加操作符
- -= 赋值减操作符
- *= 赋值乘操作符
- /= 赋值除操作符
- %= 赋值求余操作符
- ^= 赋值求幂操作符
- **= 赋值求幂操作符
- PS:需要注意的是,如果某模式为=号,此时使用/=/可能会有语法错误,应以/[=]/替代;
awk中,任何非0值或非空字符串都为真,反之就为假;
五、比较操作符
- 操作符 描述
- > 大于
- < 小于
- >= 大于等于
- <= 小于等于
- == 等于
- != 不等于
- ~ 匹配
- !~ 匹配取反
&& :逻辑与
|| :逻辑或
例:
打印系统上uid大于等于500且以m开头的行的首字段;&&与
- [root@mos ~]# awk -F: '$3>=500 && $1 ~ /^m/{print $1}' /etc/passwd
- mos
- mos1
- [root@mos ~]# awk -F: '$3>=500 || $1 ~/^v/{print $1}' /etc/passwd
- vcsa
- nfsnobody
- student
- visitor
- mos
- mos1
- [root@mos ~]# awk -F: '$3>=500 && $1 ~/^m/|| $3>=500 && $1 ~/^v/{print $1}' /etc/passwd
- visitor
- mos
- mos1
selector?if=true=exp:if=false=exp
selector是条件,例如使用index函数判断一个变量中有无特定字符;有无则输出特定表达式if=true=exp:if=false=exp,如下例:
- [root@mos ~]# awk 'BEGIN{msg="My name is MOS!";print index(msg,"MOS")?"ok":"no";}'
- ok
- [root@mos ~]# awk 'BEGIN{msg="My name is MOS!";print index(msg,"AAA")?"ok":"no";}'
- no
function_name (parament1,parament2...)
用法
...您看上面,index函数的例子...对头,就那么用的。关于函数和以上的例子,在awk的模式介绍完后,基本都会有.
上面的关于逻辑运算符&&和||的例子中,已经用到了awk的模式,其以m和v开头的和大于等于500的运算,分别是表达式expression和正则表达式regexp,需要说明的是,其还支持取反和模糊匹配等,如下例及各种例:
- [root@mos download]# awk -F: '/^root/{print $1,$NF}' /etc/passwd
- root /bin/bash
- [root@mos download]# awk -F: '!/^root/{print $1,$NF}' /etc/passwd|head -2
- bin /sbin/nologin
- daemon /sbin/nologin
- [root@mos ~]# awk -F: '$3~0{print}' /etc/passwd
- root:x:0:0:root:/root:/bin/bash
- uucp:x:10:14:uucp:/var/spool/uucp:/sbin/nologin
- .........
- [root@mos ~]# awk -F: '$3==0{print}' /etc/passwd
- root:x:0:0:root:/root:/bin/bash
- [root@mos ~]# awk '/^visitor/,/^mos1/{print}' /etc/passwd
- visitor:x:501:501::/home/visitor:/bin/bash
- mos:x:502:502::/home/mos:/bin/bash
- mos1:x:503:503::/home/mos1:/bin/bash
- [root@mos download]# awk -F: 'BEGIN {print "Name\tShell"}{print $1,"\t",$NF}END{print "---End---"}' /etc/passwd
- Name Shell
- root /bin/bash
- ................
- mysql /bin/bash
- ---End---
- [root@mos ~]# awk -F: 'BEGIN{print "Username UID"}$3>=500 && $1 ~ /^m/{printf "%-15s%s\n",$1,$3}END{print "---END---"}' /etc/passwd
- Username UID
- mos 502
- mos1 503
- ---END---
- [root@mos ~]# awk -F: 'BEGIN{print "Username UID"}{printf "%-15s%s\n",$1,$3}END{print "---END---"}' /etc/passwd 去掉条件匹配,打印所有.
- [root@mos download]# awk -F: 'BEGIN {count=0}$NF ~/nologin/ {count++}END{print "Nologin number is:",count}' /etc/passwd
- Nologin number is: 30
- [root@mos ~]# awk 'BEGIN{print "a""b"}'
- ab
- [root@mos ~]# awk 'BEGIN{print "a","b"}'
- a b
- [root@mos ~]# awk -v OFS=\~ 'BEGIN{print "a","b"}'
- a~b
- [root@mos download]# awk 'BEGIN{FS=":"}{print $1}' /etc/passwd|head -2
- root
- bin
- [root@mos download]# awk -F: '{if ($3<=499)print $1,"Sys User";else print $1,"Common User."}' /etc/passwd
- root Sys User
- ...........
- mos1 Common User.
- mysql Sys User
- [root@mos download]# awk -F: '{if($3==0){print $1,"Admin User";}else if($3>0 && $3<=499){print $1,"Sys User";}else{print $1,"Comm User"}}' /etc/passwd
- root Admin User
- bin Sys User
- .............
- nfsnobody Comm User
- ............
- oprofile Sys User
- ....................
- mos1 Comm User
- mysql Sys User
- [root@mos download]# awk -F: '$1!~/root/ && $1 !~/^$/{i=1;while(i<=4){print $i;i++}}' /etc/passwd|head -4
- bin
- x
- 1
- 1
- # awk -F: '$1!~/root/{i=1;while(i<=NF){print $i;i+=2}}' /etc/passwd while奇
- # awk -F: '$1!~/root/{i=2;while(i<=NF){print $i;i+=2}}' /etc/passwd while偶
- # awk -F: '{for(i=1;i<=NF;i+=2) print $i}' /etc/passwd for奇
- # awk -F: '{for(i=2;i<=NF;i+=2) print $i}' /etc/passwd for偶
- [root@mos download]# awk 'BEGIN{A[10]="hello";A[15]="world";print A[10],A[15]}'
- hello world
- [root@mos download]# awk 'BEGIN{A["m"]="hello";A["n"]="world";print A["m"],A["n"]}'
- hello world
- [root@mos download]# awk 'BEGIN{A["m"]="hello";A["n"]="world";for(B in A)print A[B],"OK"}'
- hello OK
- world OK
- [root@mos download]# awk 'BEGIN{for(k in ENVIRON){print k"="ENVIRON[k],"OK";}}'
- AWKPATH=.:/usr/share/awk OK
- OLDPWD=/root OK
- .........
- [root@mos download]# netstat -ant|awk '$1~/tcp/{S[$NF]++}END{for (A in S) printf "%-15s:%s\n",A,S[A]}'
- LISTEN :11
- ESTABLISHED :2
- [root@mos download]# awk -F: '$NF!~/^$/{S[$NF]++}END{for (A in S)print A,S[A]}' /etc/passwd
- /bin/sync 1
- /bin/bash 6
- /sbin/nologin 30
- /sbin/halt 1
- /sbin/shutdown 1
- [root@mos download]# awk 'BEGIN{res=0;i=0;do{res+=i;i++;}while(i<=100)print res;}'
- 5050
- [root@mos download]# awk 'BEGIN{while(i<=100){res+=i;i++;}print res;}'
- 5050
- [root@mos ~]# time(awk 'BEGIN{res=0;for(i=0;i<=10000;i++){res+=i;}print res;}')
- 50005000
- real 0m0.003s
- user 0m0.001s
- sys 0m0.001s
- [root@mos ~]# time(res=0;for i in $(seq 10000);do res=$(($res+i));done;echo $res;)
- 50005000
- real 0m0.114s
- user 0m0.097s
- sys 0m0.011s
- # awk '{IP[$1]++}END{for(A in IP)print IP[A],A}' access_log|sort -rn|head -5
- [root@mos download]# awk 'BEGIN{srand();fr=int(1000*rand());print fr;}'
- 796
- [root@mos download]# awk 'BEGIN{srand();fr=int(1000*rand());print fr;}'
- 224
- [root@mos ~]# awk 'BEGIN{lab="2My name is MOS2012.";gsub(/[0-9]+/,"--demo--",lab);print lab}'
- --demo--My name is MOS--demo--.
- [root@mos download]# awk 'BEGIN{res="My name is MOS!";print match(res,/[0-9]+/)?"ok":"no";}'
- no
- [root@mos download]# awk 'BEGIN{res="My name is MOS88!";print match(res,/[0-9]+/)?"ok":"no";}'
- ok
- [root@mos ~]# awk 'BEGIN{info="My Name is MOS!";print substr(info,4,4);}'
- Name
- [root@mos ~]# awk 'BEGIN{test="My name is MOS.";split(test,Ary," ");for(l in Ary){print l,Ary[l];}print length(Ary),"Str Len";}'
- 4 MOS.
- 1 My
- 2 name
- 3 is
- 4 Str Len
- [root@mos ~]# awk -v FS=: 'BEGIN{while("cat /etc/passwd"|getline){print $1;};close("/etc/passwd");}'|head -3
- root
- bin
- daemon
- [root@mos ~]# awk 'BEGIN{while(getline<"/etc/passwd"){print $0,"OK";};close("/etc/passwd");}'|tail -3
- mos:x:502:502::/home/mos:/bin/bash OK
- mos1:x:503:503::/home/mos1:/bin/bash OK
- mysql:x:27:27:MySQL Server:/var/lib/mysql:/bin/bash OK
- [root@mos download]# awk 'BEGIN{D=system("df -hP");print D;}'
- Filesystem Size Used Avail Use% Mounted on
- /dev/mapper/My_vg-lv_root 9.7G 3.1G 6.2G 33% /
- /dev/mapper/My_vg-lv_home 496M 19M 452M 4% /home
- /dev/sda1 99M 13M 82M 13% /boot
- tmpfs 1014M 0 1014M 0% /dev/shm
- /dev/hdc 3.3G 3.3G 0 100% /rhel_dvd
- [root@mos ~]# Out="My name is MOS."
- [root@mos ~]# echo|awk '{print res}' res="$Out"
- My name is MOS.
- [root@mos ~]# echo|awk -v res1="$Out" 'BEGIN{print res1}'
- My name is MOS.
- [root@mos ~]# echo|awk -v res1="$Out" '{print res1}'
- My name is MOS.
- [root@mos download]# awk 'BEGIN{Tim=mktime("2012 12 21 23 59 59");print strftime("%c",Tim);}'
- Fri 21 Dec 2012 11:59:59 PM CST
- [root@mos download]# awk 'BEGIN{Time=mktime("2012 12 21 23 59 59");Time1=mktime("2012 12 21 23 59 01");print Time-Time1;}'
- 58
- [root@mos download]# awk 'BEGIN{Time=mktime("2012 12 21 23 59 59");Time1=systime();print Time1-Time;}'
- 535294