文本处理工具-awk

文本处理工具awk

awk的名字由来:创始人Aho, Weinberger, Kernighan三人的首字母

有多种版本:New awk(nawk),GNU awk(gawk)

 .gawk   模式扫描和处理语言

  基本用法:

awk [options] ‘program’ var=value file…

awk [options] -f programfile var=value file…

awk [options] 'BEGIN{ action;… } pattern{ action;… } END{

action;… }' file …

注:awk 程序通常 由:BEGIN 语句 块、能够使用模式匹配的通用语句块、END 语句块,共3 部分 组成program 通常是被单引号或双引号中

选项:

-F 指明输入时用到的字段分隔符

-v var=value: 自定义变量

-f scrifile :调用awk命令

基本格式:

awk [options] 'program' file…

program:pattern{action statements;..}

pattern 和action: :

• pattern 部分决定动作语句何时触发及触发事件(BEGIN,END)

• action statements对 对 数据进行处理,放在{} 内指明(print, printf)

分割符、域和记录

• awk 执行时,由分隔符分隔的字段(域)标记$1,$2..$n称为域标识。$0为所有域。

注意:和shell中变量$符含义不同

• 文件的每一行称为记录

• 省略action行,则默认执行print $0的操作

 print 格式:print item1, item2, …

  要点 :

• (1) 逗号分隔符

• (2) 输出的各item 可以字符串,也可以是数值;当前记录的字段 、变量或awk的表达式

• (3) 如省略item ,相当于print $0

1:打印hello awk 用/etc/issue的行

[root@lxc ~]# awk '{print "hello awk"}' /etc/issue

hello awk

hello awk

hello awk

[root@lxc ~]#

2:显示系统中所有的用户名和UID

[root@lxc ~]# awk -F: '{print $1 "\t" $3}' /etc/passwd

root 0

bin 1

daemon 2

adm 3

lp 4

sync 5

……

.awk变量

变量:内置和自定义变量

 FS:输入字段分隔符,默认为空白字符

例:

[root@lxc ~]# awk -v FS=":" '{print $1,FS,$3}' /etc/passwd

root : 0

bin : 1

daemon : 2

adm : 3

lp : 4

sync : 5

……

 OFS:输出字段分隔符,默认为空白字符

例:

[root@lxc ~]# awk -v FS=":" -v OFS="====" '{print $1,$3}' /etc/passwd

root====0

bin====1

daemon====2

adm====3

lp====4

sync====5

shutdown====6

……

 RS :输入记录分隔符,指定输入时的换行符原换行符仍有效

例:

[root@lxc ~]# cat test.txt

a b c

dd ee ff

gg

[root@lxc ~]# awk -v RS=" " '{print $1}' test.txt

a

b

c

ee

ff

[root@lxc ~]#

 ORS :输出记录分隔符,输出时用指定符号代替换行符

例:

[root@lxc ~]# awk -v RS=" " -v ORS="=" '{print $1}' test.txt

a=b=c=ee=ff=[root@lxc ~]# cat test.txt

a b c

dd ee ff

gg

[root@lxc ~]#

 NF :字段数量

1:打印字段数量

[root@lxc ~]# awk -F: '{print NF}' /etc/passwd

7

7

7

7

7

……

2:显示最后一个字段

[root@lxc ~]# awk -F: '{print $NF}' /etc/passwd

/bin/bash

/sbin/nologin

/sbin/nologin

/sbin/nologin

/sbin/nologin

 ……

 NR :行号

例:

[root@lxc ~]# awk -F: '{print NR}' /etc/passwd

1

2

3

4

5

6

……

 FNR :各文件分别计数, 行号

例:

[root@lxc ~]# awk '{print FNR}' test.txt /etc/issue

1

2

3

1

2

3

[root@lxc ~]#

 FILENAME :当前文件名

例:

[root@lxc ~]# awk -F: '{print FNR,FILENAME,$1}' /etc/issue test.txt

1 /etc/issue CentOS release 6.8 (Final)

2 /etc/issue Kernel \r on an \m

3 /etc/issue

1 test.txt a b c

2 test.txt dd ee ff

3 test.txt gg

[root@lxc ~]#

 ARGC :命令行参数的个数

[root@lxc ~]# awk '{print ARGC}' /etc/fstab /etc/inittab

3

3

3

……

 ARGV :数组,保存的是命令行所给定的各参数(不理解)

例:

[root@lxc ~]# awk 'BEGIN {print ARGV[0]}' /etc/fstab

awk

[root@lxc ~]#

自定义变量

(1) -v var=value 变量名区分字符大小写

(2) 在program中直接定义

1:

[root@lxc ~]# awk -F: -v name="username" -v uid="uid" '{print name":"$1,"\t"uid":"$3}' /etc/passwd

username:root uid:0

username:bin uid:1

username:daemon uid:2

username:adm uid:3

username:lp uid:4

……

2:

[root@lxc ~]# awk -F: '{n="haha";m="xixi";print n,m}' /etc/passwd

haha xixi

haha xixi

haha xixi

haha xixi

haha xixi

……

.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

      + :显示数值的号 正负符号 %+d

1:

[root@lxc ~]# awk -F: '{printf "%s %d\n",$1,$3}' /etc/passwd

root 0

bin 1

daemon 2

adm 3

lp 4

sync 5

……

2:

[root@lxc ~]# awk -F: '{printf "%s\n",$1}' /etc/passwd

root

bin

daemon

adm

lp

……

3:

[root@lxc ~]# awk -F: '{printf "username: %s\n",$1}' /etc/passwd

username: root

username: bin

username: daemon

……

4:

[root@lxc ~]# awk -F: '{printf "username: %15s,uid:%d\n",$1,$3}' /etc/passwd

username:            root,uid:0

username:             bin,uid:1

username:          daemon,uid:2

username:             adm,uid:3

username:              lp,uid:4

……

5:

[root@lxc ~]# awk -F: '{printf "username: %-15s,uid:%d\n",$1,$3}' /etc/passwd

username: root           ,uid:0

username: bin            ,uid:1

username: daemon         ,uid:2

username: adm            ,uid:3

username: lp             ,uid:4

username: sync           ,uid:5

……

.操作符

  算术操作符:

x+y, x-y, x*y, x/y, x^y, x%y

-x:  转换为负数

+x:  转换为数值

  字符串操作符:没有符号的操作符,字符串连接

   赋值操作符:=, +=, -=, *=, /=, %=, ^=,++, —

例:

[root@lxc ~]# awk 'BEGIN{n=1;m=2;print m+=n}'

3

[root@lxc ~]#

   比较操作符:>, >=, <, <=, !=, ==

例:

[root@lxc ~]# awk -F: '$3 > 1000 {print $1,$3}' /etc/passwd

nfsnobody 65534

[root@lxc ~]#

 

  模式匹配符:

~ :左边是否和右边匹配包含

!~ :是否不匹配

例:

[root@lxc ~]# awk '$0 !~ /root/' /etc/passwd

bin:x:1:1:bin:/bin:/sbin/nologin

daemon:x:2:2:daemon:/sbin:/sbin/nologin

adm:x:3:4:adm:/var/adm:/sbin/nologin

lp:x:4:7:lp:/var/spool/lpd:/sbin/nologin

……

 

逻辑操作符:与&& ,或|| ,非!

例:

[root@lxc ~]# awk -F: '!($3==0 || $3 >=1000){print $1,$3}' /etc/passwd

bin 1

daemon 2

adm 3

lp 4

sync 5

shutdown 6

……

 

函数调用:function_name(argu1, argu2, …)

条件表达式(三目表达式):

selector?if-true-expression:if-false-expression

例:

[root@lxc ~]# awk -F: '{$3>=1000?usertype="Commom user":usertype="susadmin sysuser";printf"%15s:%-s\n",$1,usertype}' /etc/passwd

           root:susadmin sysuser

            bin:susadmin sysuser

         daemon:susadmin sysuser

            adm:susadmin sysuser

             lp:susadmin sysuser

           sync:susadmin sysuser

       shutdown:susadmin sysuser

……

PATTERN: 根据pattern 条件,过滤匹配的行,再做处理

(1) 如果未指定:空模式,匹配每一行

(2) /regular expression/:仅处理能够模式匹配到的行,需要用/ /括起来

(3) relational expression: 关系表达式,结果有“真”有“假”,结果为“真”才会被处理。

真:结果为非0值,非空字符串

假:结果为空字符串或0值

1:结果为假不处理

 

[root@lxc ~]# awk '"" {print $0}' /etc/fstab

[root@lxc ~]#

2:结果为真处理

[root@lxc ~]# awk '1{print $0}' /etc/fstab

 

#

# /etc/fstab

# Created by anaconda on Thu Nov  3 19:08:05 2016

#

# Accessible filesystems, by reference, are maintained under '/dev/disk'

# See man pages fstab(5), findfs(8), mount(8) and/or blkid(8) for more info

……

3:

[root@lxc ~]# awk -F: '$NF=="/bin/bash"{print $1,$NF}' /etc/passwd

root /bin/bash

lxc /bin/bash

[root@lxc ~]#

4:

[root@lxc ~]# awk -F: '$NF!~"/bin/bash"{print $1,$NF}' /etc/passwd“

bin /sbin/nologin

daemon /sbin/nologin

adm /sbin/nologin

lp /sbin/nologin

sync /bin/sync

shutdown /sbin/shutdown

……

(4) line ranges:行范围

startline,endline :/pat1/,/pat2/  不支持直接给出数字格式

1:

[root@lxc ~]# awk -F: '/^root/,/^lp/' /etc/passwd

root:x:0:0:root:/root:/bin/bash

bin:x:1:1:bin:/bin:/sbin/nologin

daemon:x:2:2:daemon:/sbin:/sbin/nologin

adm:x:3:4:adm:/var/adm:/sbin/nologin

lp:x:4:7:lp:/var/spool/lpd:/sbin/nologin

[root@lxc ~]#

2:

[root@lxc ~]# awk -F: 'NR>=10 && NR<=15 {print NR,$0}' /etc/passwd

10 uucp:x:10:14:uucp:/var/spool/uucp:/sbin/nologin

11 operator:x:11:0:operator:/root:/sbin/nologin

12 games:x:12:100:games:/usr/games:/sbin/nologin

13 gopher:x:13:30:gopher:/var/gopher:/sbin/nologin

14 ftp:x:14:50:FTP User:/var/ftp:/sbin/nologin

15 nobody:x:99:99:Nobody:/:/sbin/nologin

[root@lxc ~]#

 

(5) BEGIN/END模式

BEGIN{}: 仅在开始处理文件中的文本之前执行一次

END{}:仅在文本处理完成之后执行

1:

[root@lxc ~]# awk -F: 'BEGIN{print "linenumber username"}NR>10&&NR<=15{print NR,$0}' /etc/passwd

linenumber username

11 operator:x:11:0:operator:/root:/sbin/nologin

12 games:x:12:100:games:/usr/games:/sbin/nologin

13 gopher:x:13:30:gopher:/var/gopher:/sbin/nologin

14 ftp:x:14:50:FTP User:/var/ftp:/sbin/nologin

15 nobody:x:99:99:Nobody:/:/sbin/nologin

[root@lxc ~]#

2:

[root@lxc ~]# awk -F: 'BEGIN{print "linenumber username"}NR>10 && NR<=15{print NR,$0}END{print "end"}' /etc/passwd

linenumber username

11 operator:x:11:0:operator:/root:/sbin/nologin

12 games:x:12:100:games:/usr/games:/sbin/nologin

13 gopher:x:13:30:gopher:/var/gopher:/sbin/nologin

14 ftp:x:14:50:FTP User:/var/ftp:/sbin/nologin

15 nobody:x:99:99:Nobody:/:/sbin/nologin

end

[root@lxc ~]#

3:

[root@lxc ~]# seq 10 | awk 'i=0'

[root@lxc ~]# seq 10 | awk 'i=1'

1

2

3

4

5

6

7

8

9

10

[root@lxc ~]# seq 10 | awk 'i=!i'

1

3

5

7

9

[root@lxc ~]# seq 10 |awk '{i=!i;print i}'

1

0

1

0

1

0

1

0

1

0

[root@lxc ~]# seq 10 |awk '!(i=!i)'

2

4

6

8

10

[root@lxc ~]# seq 10 |awk -v i=1 'i=!i'

2

4

6

8

10

[root@lxc ~]#

.awk 控制语句

 { statements;… }  组合语句

 if(condition) {statements;…}

 if(condition) {statements;…} else {statements;…}

 while(conditon) {statments;…}

 do {statements;…} while(condition)

 for(expr1;expr2;expr3) {statements;…}

 break

 continue

 delete array[index]

 delete array

 exit

if-else

语法:if(condition) statement [else statement]

if(condition1){statement1}else if(condition2){statement2}

else{statement3}

  使用场景:对awk取得的整行或某个字段做条件判断

1:显示普通用户的用户名和UID

[root@lxc ~]# awk -F: '{if ($3>=500) print $1,$3}' /etc/passwd

nfsnobody 65534

lxc 500

[root@lxc ~]#

2:显示磁盘利用率超过80%的

[root@lxc ~]# df -h |awk -F% '/^\/dev/{print $1}'|awk '{if($NF>80)print $1,$5}'

[root@lxc ~]#

3:判断成绩

[root@lxc ~]# awk 'BEGIN{test=100;if(test>90){print "very good"}else if(test>60){prin t good""}else{print "no pass"}}'

very good

[root@lxc ~]#

 while 循环

  语法:while(condition){statement;…}

  条件“真”,进入循环;条件“假”, 退出循环

  使用场景:对一行内的多个字段逐一类似处理时使用

       对数组中的各元素逐一处理时使用

例:显示文件中以linux16为行首(行首可有空格)的行中的各个字段及所字段字符串的长度

[root@localhost ~]# awk '/^[[:space:]]*linux16/{i=1;while(i<=NF) {if(length($i)>=10)> {print $i,length($i)}; i++}}' /etc/grub2.cfg

/vmlinuz-3.10.0-327.el7.x86_64 30

root=/dev/mapper/centos-root 28

crashkernel=auto 16

rd.lvm.lv=centos/root 21

rd.lvm.lv=centos/swap 21

net.ifnames=0 13

/vmlinuz-0-rescue-0dc32f41d52e4e3a9bd9a30a2683ae5d 50

root=/dev/mapper/centos-root 28

crashkernel=auto 16

rd.lvm.lv=centos/root 21

rd.lvm.lv=centos/swap 21

net.ifnames=0 13

[root@localhost ~]#

   do-while 循环

  语法:do {statement;…}while(condition)

  意义:无论真假,至少执行一次循环体

例:1~100的自然数的和

[root@lxc ~]# awk 'BEGIN{sum=0;i=0;do{sum+=i;i++;}while(i<=100);print sum}'

5050

[root@lxc ~]#

   for 循环

  语法:for(expr1;expr2;expr3) {statement;…}

  常见用法:

for(variable assignment;condition;iteration process)

{for-body}

  特殊用法:能够遍历数组中的元素;

  语法:for(var in array) {for-body}

例:1~100的自然数的和

[root@lxc ~]# awk 'BEGIN{total=0;for(i=1;i<=100;i++){total+=i}{print total}}'

5050

[root@lxc ~]#

2:

1~100之间的奇数之和

[root@lxc ~]# awk 'BEGIN{sum=0;for(i=1;i<=100;i++){if(i%2==1)continue;sum+=i};print sum}'

2550

[root@lxc ~]#

 switch 语句

  语法: :switch(expression) {case VALUE1 or /REGEXP/:

statement1; case VALUE2 or /REGEXP2/: statement2;

…; default: statementn}

 break 和continue

例:

[root@lxc ~]# awk 'BEGIN{sum=0;for(i=1;i<=100;i++){if (i%2==0)break;sum+=i}print sum}'

1

[root@lxc ~]#

 next:提前结束对本行处理而直接进入下一行处理(awk自身循环)

例:

[root@lxc ~]# awk -F: '{if ($3%2==0)netx;print$1,$3}' /etc/passwd

root 0

bin 1

daemon 2

adm 3

lp 4

……

.awk数组

   关联数组:array[index-expression]

index-expression:

(1) 可使用任意字符串;字符串要使用双引号括起来

(2) 如果某数组元素事先不存在,在引用时,awk 会自动创建此元素,并将其值初始化为“空串”

注:若要判断数组中是否存在某元素,要使用“index in array”格式进行遍历

1:

[root@lxc ~]# awk 'BEGIN{arr["frist"]="mage";arr["second"]="laowang";print arr["frist"]}'

mage

[root@lxc ~]#

2:

[root@lxc~]# awk' BEGIN{weekdays["mon"]="Monday";weekdays["tue"]="Tuseday";for(i in weekdays){print weekdays[i]}}'

Monday

Tuseday

[root@lxc ~]#

   数值处理:

   rand():返回0和1之间一个随机数

[root@lxc ~]# awk 'BEGIN{srand();for (i=1;i<=5;i++)print int(rand()*100)}'

5

17

68

52

49

[root@lxc ~]#

  字符串处理:

• length([s]) :返回指定字符串的长度

• sub(r,s,[t]) :对t字符串进行搜索r表示的模式匹配的内容,并将第一个匹配的内容替换为s

例:

[root@lxc ~]# echo "2008:08:08 08:08:08" | awk 'sub(/:/,"-",$1)'

2008-08:08 08:08:08

[root@lxc ~]#

• gsub(r,s,[t]) :对t字符串进行搜索r表示的模式匹配的内容,并全部替换

s所表示的内容

例:

[root@lxc ~]# echo "2008:08:08 08:08:08" | awk 'gsub(/:/,"-")'

2008-08-08 08-08-08

[root@lxc ~]#

• split(s,array,[r]) :以r 为分隔符,切割字符s,并将切割后的结果保存至array所表示的数组中,第一个索引值为1, 第二个索引值为2,…

例:

[root@lxc ~]# netstat -tan |awk '/^tcp\>/{split($5,ip,":");count[ip[1]]++}END{for (i in count){print i,count[i]}}'

 7

172.16.253.83 1

0.0.0.0 6

[root@lxc ~]#

自定义函数

  格式:

function name ( parameter, parameter, … ) {

statements

return expression

}

例:

 

[root@lxc ~]# cat fun.awk

function funmin(num1,num2){

num1<num2?min=num1:min=num2

return min

}

BEGIN{n1=100; n2=200;print funmin(n1,n2)}

[root@lxc ~]# awk -f fun.awk

100

[root@lxc ~]#

  system 命令

  空格是awk中的字符串连接符,如果system中需要使用awk中的变量可以使用空格分隔,或者说除awk的变量外其他一律用""引用起来。

例:

[root@lxc ~]# awk 'BEGIN{score=100;system("echo your score is " score)}'

your score is 100

[root@lxc ~]#

  awk程序写成脚本,直接调用或执行

例:

[root@lxc ~]# cat f1.awk

#!/bin/awk -f

{if($3>=1000)print $1,$3}

[root@lxc ~]# ./f1.awk -F: /etc/passwd

nfsnobody 65534

[root@lxc ~]#

    向脚本传递参数

    格式:awkfile var=value var2=value2… Inputfile

例:

[root@lxc ~]# cat test.awk

#!/bin/awk -f

{if ($3>=min && $3<=max)print $1,$3}

 

[root@lxc ~]# ./test.awk -F: min=100 max=200 /etc/passwd

usbmuxd 113

avahi-autoipd 170

abrt 173

[root@lxc ~]#

原创文章,作者:changge,如若转载,请注明出处:http://www.178linux.com/61516

(0)
changgechangge
上一篇 2016-11-29
下一篇 2016-11-29

相关推荐

  • Linux nginx 服务

                           Linux nginx 服务 Nginx服务简介:      NGINX :是一个自由、开源、高性能、轻量级的HT…

    系统运维 2016-11-18
  • 正则表达式

    Regual Expression 由一类特殊字符及文本字符所编写的模式,其中有些字符不表示字面意义,而是用于控制或通配的功能 分类 REGEXP:由一类特殊字符及文本字符所编写的模式,其中有些字符(元字符)不表示字符字面意义,而表示控制或通配的功能 程序支持:grep, vim, less,nginx等 分两类: 基本正则表达式:BRE 扩展正则表达式:E…

    Linux干货 2016-08-07
  • mkdir练习

    课外资料 mkdir命令用来创建目录。该命令创建由dirname命名的目录。如果在目录名的前面没有加任何路径名,则在当前目录下创建由dirname指定的目录;如果给出了一个已经存在的路径,将会在该目录下创建一个指定的目录。在创建目录时,应保证新建的目录与它所在目录下的文件没有重名。 注意:在创建文件时,不要把所有的文件都存放在主目录中,可以创建子目录,通过它…

    Linux干货 2016-08-08
  • bash脚本编程实例

    bash脚本编程实例 1.写一个脚本,使用ping命令探测172.16.250.1-172.16.250.254之间的所有主机的在线状态 在线的主机使用绿色显示 不在线的主机使用红色显示 #!/bin/bash for i in {1..254};do if /bin/ping -W 1 -c 1 172.16.250.${i} >> /dev/…

    Linux干货 2017-08-20
  • lamp+nfs搭建wordpress

    一、前言 lamp是大多上公司常用的架构,本文将针对分离式的lamp+nfs来搭建一个简单的wordpress网站。 二、架构图 三、基本实现过程 3.1:dns搭建 由于这这是一个实验,故使用yum搭建dns服务器 yum install -y bind 配置如下 dns主配置文件 dns辅助配置文件 zone文件 对所有服务…

    Linux干货 2015-10-16
  • 第5周作业

    1、显示当前系统上root、fedora或user1用户的默认shell     ~]# egrep "^(root|fedora|user1)" /etc/passwd 2、找出/etc/rc.d/init.d/functions文件中某单词后面跟一组小括号的行,如:hello();  …

    Linux干货 2017-01-07