介绍AWK用法

awk与grep,sed号称正则表达式三剑客。他们分别适合不同的需求。

grep适合文本过滤。查找某些关键的行与字符串。

sed适合编辑文本。

AWK:适合文本处理与报表生成。在linux上的AWK为GAWK,当然使用的时候只要执行AWK命令就行,会自动调用GAWK。awk处理文本是这样的,每读进一行,就将其分隔成单独的字段来处理,默认分隔符为空格。如下图,

一,awk的语法结构:

awk [options] 'PATTERN {action}'   file1,file2......

1,常用options有两个

 (1)-v:声明一个变量

  FS为awk内置变量,FS的默认值为空格,且FS表示输入分隔符,下面这条语句表示改变默认分隔符。内置变量在下面会解释

  
  
  
  
  1. [root@server30 ~]# awk -v FS=: '{print $1}' /etc/passwd

  2. root

  3. bin

  4. daemon

  5. adm

  6. lp

  7. sync

  8. shutdown

如果不改变默认分符时,得到是下面的结果,将整行都输出来。默认输入输出的分隔符都空格。

  
  
  
  
  1. [root@server30 ~]#  awk '{print $1}' /etc/passwd

  2. root:x:0:0:root:/root:/bin/bash

  3. bin:x:1:1:bin:/bin:/sbin/nologin

  4. daemon:x:2:2:daemon:/sbin:/sbin/nologin

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

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

  7. sync:x:5:0:sync:/sbin:/bin/sync

 (2)-F:指定输入分隔符,下面表示指定以:为输入分隔符

  
  
  
  
  1. [root@server30 ~]# awk -F: '{print $1}' /etc/passwd

  2. root

  3. bin

  4. daemon

  5. adm

  6. lp

上面属于print 属于动作(action),使用print,如果有多个字段要显示出来,则需要用逗号将不同字段分隔,以说明是不同两个字段,如果不说明,则输出时会当作一个字段来显示。

用逗号明确告诉awk $1和$3为不同的字段。默认输出的分格符是空格,因此得到两个不同的字段。

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

  2. root 0

  3. bin 1

  4. daemon 2

  5. adm 3

  6. lp 4

如果不用逗号隔开$1和$3,则会得到下面的结果,将两个字段合并起来。

  
  
  
  
  1. [root@server30 ~]# awk -F: '{print $1 $3}' /etc/passwd

  2. root0

  3. bin1

  4. daemon2

  5. adm3

  6. lp4

因此从上面结果可以看print的语法: print item1,item2......

还有一个常用printf,而printf比print更好用,printf的语法

printf format  item1,item2 .....

format的格式有以下几种:

       %c: 显示字符的ASCII码;

%d, %i:十进制整数;

%e, %E:科学计数法显示数值;

%f: 显示浮点数;

%g, %G: 以科学计数法的格式或浮点数的格式显示数值;

%s: 显示字符串;

%u: 无符号整数;

%%: 显示%自身;

对format的修饰符有常用有下面6个:与format结合使用

       N:显示宽度,%10s表示每个字段显示10个字符的宽度

-:表示左对齐,默认是右对齐

+:显示数值的符号,如果是正数则显示正号,负数则显示负号

       \n表示输出新的一行;

\t表示水平的tab按键;

\v垂直的tab按键;

下面语句中%10s,表示$1显示10个字符的宽度,如果$1小于10字符的宽度,则用空白补充,$5原来是多宽,就多宽,且不自动换行。下面结果在同一行显示

  
  
  
  
  1. [root@server30 ~]# awk '{printf "%10s,%s",$1,$5}' /etc/issue

  2. Red,Server    Kernel,\m          ,     RH033,[root@server30 ~]#


加了\n后,每一行显示完$5后会自动换行,但是结果是右对齐,因为默认是右对齐。结果如下:注意格式之间不能用逗号,不然也会打印出来。

  
  
  
  
  1. [root@server30 ~]# awk '{printf "%10s,%s\n",$1,$5}' /etc/issue

  2.       Red,Server

  3.    Kernel,\m

  4.          ,

  5.     RH033,

这样的输出我们自己看来都觉得很乱,因此还需要加-,使结果左对齐,我这在格式之间没有加逗号。

  
  
  
  
  1. [root@server30 ~]# awk '{printf "%-10s%s\n",$1,$5}' /etc/issue

  2. Red        Server

  3. Kernel     \m

  4. RH033

2,内置变量:

(1)NF(number of filed):当每行field的个数。(不加$,只用NF表示每一行有多少字段,如果用$NF表示只显示每一行最后一个字段)

NF前不加$的结果:显示每行有多少个字段

  
  
  
  
  1. [root@server30 ~]# awk '{print NF}' /etc/issue

  2. 8

  3. 5

  4. 0

  5. 1

NF前面加$表示,只显示每行的最后

  
  
  
  
  1. [root@server30 ~]# awk '{print $NF}' /etc/issue

  2. (Tikanga)

  3. \m

  4. RH033

(2)FS(field separator):输入分隔符,默认分隔符是空白字符。前面已经举例。

(3)OFS(out field separator):输出分隔符,默认输出分隔符了是空白字符。

改变输出分隔符如下:

  
  
  
  
  1. [root@server30 ~]# awk -F: -v OFS=: '{print $1,$7}' /etc/passwd

  2. root:/bin/bash

  3. bin:/sbin/nologin

  4. daemon:/sbin/nologin

  5. adm:/sbin/nologin

  6. lp:/sbin/nologin

如果不定义OFS则默认是空格

  
  
  
  
  1. [root@server30 ~]# awk -F: '{print $1,$7}' /etc/passwd

  2. root /bin/bash

  3. bin /sbin/nologin

  4. daemon /sbin/nologin

  5. adm /sbin/nologin

  6. lp /sbin/nologin

(4)NR表示 当前处理第几行数据。\t在前面已经解释过

  
  
  
  
  1. [root@server30 ~]# awk -F: '{print $1 "\tline:" NR}' /etc/passwd

  2. root    line:1

  3. bin     line:2

  4. daemon  line:3

  5. adm     line:4

  6. lp      line:5

(5)RS: Record separator,默认是换行符;

3,常见的模式类型:

(1)Regexp: 正则表达式,格式为/regular expression/

如果某行包含bash字符串,则就显示出来 /bash/为正则表达式

  
  
  
  
  1. [root@server30 ~]# awk -F: '/bash/{print $0}' /etc/passwd

  2. root:x:0:0:root:/root:/bin/bash

  3. student:x:500:500::/home/student:/bin/bash

  4. redhat:x:501:501::/home/redhat:/bin/bash

  5. magedu:x:502:502::/home/magedu:/bin/bash

(2)expresssion: 表达式,其值非0或为非空字符时满足条件,如:$1 ~ /foo/ 或 $1 == "magedu",用运算符~(匹配)和~!(不匹配)。

如果第三个字段大于500,则显示出当前行的第一个字段, $3>500为表达式

  
  
  
  
  1. [root@server30 ~]# awk -F: '$3>500{print $1}' /etc/passwd

  2. nfsnobody

  3. redhat

  4. magedu

(3)Ranges: 指定的匹配范围,格式为pat1,pat2

awk '/bash/,/nologin/{print $0}' /etc/passwd其中/bash/,/nologin/表示第一次被bash匹配的,与第一次被nologin匹配到的中间所有的行

  
  
  
  
  1. [root@server30 ~]# awk '/bash/,/nologin/{print $0}' /etc/passwd

  2. root:x:0:0:root:/root:/bin/bash (2,3行符合条件)

  3. bin:x:1:1:bin:/bin:/sbin/nologin

  4. student:x:500:500::/home/student:/bin/bash

  5. redhat:x:501:501::/home/redhat:/bin/bash (4-7符合条件)

  6. magedu:x:502:502::/home/magedu:/bin/bash

  7. oprofile:x:16:16:Special user account to be used by OProfile:/home/oprofile:/sbin/nologin

(4)BEGIN/END:特殊模式,仅在awk命令执行前运行一次或结束前运行一次

BEGIN(预处理模式):执行紧跟在BEGIN的代码块

END:执行跟END后面的代码块。

awk -F: '$3>500{printf "%-15s %s\n", $1,$3}' /etc/passwd 在输出结果的第一行之前加一个说明,如果在nftnobody上面加username,65534面加

  
  
  
  
  1. [root@server30 ~]# awk -F: '$3>500{printf "%-15s %s\n", $1,$3}'  /etc/passwd

  2. nfsnobody       65534

  3. redhat          501

  4. magedu          502

awk -F: '$3>500{print "username   UID";printf "%-10s %s\n", $1,$3}' /etc/passwd 如果这样做,会造成每一行都会添加username   UID

  
  
  
  
  1. [root@server30 ~]# awk -F: '$3>500{print "username   UID";printf "%-10s %s\n", $1,$3}' /etc/passwd

  2. username   UID

  3. nfsnobody  65534

  4. username   UID

  5. redhat     501

  6. username   UID

  7. magedu     502

这样做就达到我们想要的结果awk -F: 'BEGIN{print "username   UID"} $3>500 {printf "%-10s %s\n", $1,$3}' /etc/passwd (用{}表示独立的代码块)

  
  
  
  
  1. [root@server30 ~]# awk -F: 'BEGIN{print "username   UID"} $3>500 {printf "%-10s %s\n", $1,$3}' /etc/passwd

  2. username   UID

  3. nfsnobody  65534

  4. redhat     501

  5. magedu     502

awk -F: 'BEGIN{print "username   UID"} $3>500 {printf "%-10s %s\n", $1,$3}  END{print "over"}'  /etc/passwd 在最后一行的后面添加一行说明用END。

  
  
  
  
  1. [root@server30 ~]# awk -F: 'BEGIN{print "username   UID"} $3>500 {printf "%-10s %s\n", $1,$3}  END{print "over"}'  /etc/passwd

  2. username   UID

  3. nfsnobody  65534

  4. redhat     501

  5. magedu     502

  6. over

5、Empty(空模式):匹配任意输入行;没有指定模式,所有的行都会被匹配到。

  
  
  
  
  1. [root@server30 ~]# awk -F: '{print $1}' /etc/passwd  

  2. root  

  3. bin  

  4. daemon  

  5. adm  

  6. lp


6、常用案例

(1)awk -F: '$1 ~/^root/{print $3,$4,$NF}' /etc/passwd  $1表示文本中所有行的第一个字段,^root表示如果第一个字段是root,则显示当这一行的第三个字段,第四个字段,和最后一个字段

(2)awk -F: '$1 !~/^root/{print $3,$4,$NF}' /etc/passwd 表示如果不能被匹配到则显示出来

(3)awk '{if($0 ~/^$/ )print NR }' /etc/issue  $0表示文本中全行的所有字符,^$表示空行, 如果某行是空行,NR表示处理第几行数据。打印出空行行号,与下面的效果一样

(4) akw '$0 ~/^$/{print NR }' /etc/issue打印出空行行号

[root@229 ~]# awk  '$0 ~/^$/{ print NR} ' /etc/issue

3


你可能感兴趣的:(awk)