文本处理工具-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

相关推荐

  • https介绍

    什么是https HTTP协议传输的数据都是未加密的,也就是明文的,因此使用HTTP协议传输隐私信息非常不安全。为了保证这些隐私数据能加密传输,于是网景公司设计了SSL(Secure Sockets Layer)协议用于对HTTP协议传输的数据进行加密,从而就诞生了HTTPS。SSL目前的版本是3.0,被IETF(Internet Engineering T…

    Linux干货 2017-12-04
  • 第九周

    统计可登录shell与不能登陆shell的个数 2. 写一个脚本 3.写一个脚本    4、写一个脚本,完成如下功能 脚本能够接受一个参数。 (1) 如果参数1为quit,则显示退出脚本,并执行正常退出。 (2) 如果参数1为yes,则显示继续执行脚本。 (3) 否则,参数1为其它任意值,均执行非正常退出。    5、…

    Linux干货 2016-12-26
  • 107-tomcat

    一.编程语言基础  1.1 编程语言: 硬件级:微码编程,汇编语言 系统级:C,C++,…

    2016-12-02
  • Puppet 的使用与进阶

    Puppet 基于puppet 可实现自动化重复任务, 快速部署关键性应用以及在本地或云端完成主动管理变更和快速扩展架构规模.基于master/agent 模型. 基于RPC 的通信, 基于xml 进行数据交换 define : 使用puppet 语言来定义资源的状态模拟 : 根据资源关系图, puppet 可以模拟部署无损运行测试代码强制 : 对比客户端主…

    2016-12-04
  • 2、文件通配符,文件创建、复制等操作

    1:bash特性之状态返回值 变量$?,用于保存命令执行成功与否的状态,0表示成功,1-255表示失败,以命令ls为例: 执行成功 [root@localhost ~]# ls /usr/     bin  etc  games &nbsp…

    Linux干货 2016-09-19
  • 马哥教育网络班22期+第十周课程练习

    1、请详细描述CentOS系统的启动流程(详细到每个过程系统做了哪些事情)    CentOS系统启动流程为:POST –> BootSequence(BIOS) –> BootLoader(MBR) –> Kernel(ramdisk) –> r…

    Linux干货 2016-12-13