天天看点

Linux学习笔记:awk详细用法

一、基础用法

awk:报告生成工具;把文件中读取到的每一行的每个字段分别进行格式化,然后进行显示。

1

2

3

4

5

6

7

8

9

10

11

<code>[Linux85]</code><code>#awk -h</code>

<code>Usage: awk [POSIX </code><code>or</code> <code>GNU style options] </code><code>-</code><code>f progfile [</code><code>-</code><code>-</code><code>] </code><code>file</code> <code>...</code>

<code>Usage: awk [POSIX </code><code>or</code> <code>GNU style options] [</code><code>-</code><code>-</code><code>] </code><code>'program'</code> <code>file</code> <code>...</code>

<code>POSIX options:      GNU </code><code>long</code> <code>options:</code>

<code>    </code><code>-</code><code>f progfile     </code><code>-</code><code>-</code><code>file</code><code>=</code><code>progfile</code>

<code>    </code><code>-</code><code>F fs           </code><code>-</code><code>-</code><code>field</code><code>-</code><code>separator</code><code>=</code><code>fs    </code><code>#字段分隔符</code>

<code>    </code><code>-</code><code>v var</code><code>=</code><code>val      </code><code>-</code><code>-</code><code>assign</code><code>=</code><code>var</code><code>=</code><code>val</code>

<code>    </code><code>-</code><code>m[fr] val</code>

<code>                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                          </code> 

<code>awk [options] </code><code>'script'</code> <code>FILE</code> <code>...</code>

<code>awk [options] </code><code>'/pattern/{action}'</code> <code>FILE</code> <code>...</code>

四种分隔符:

输入/输出

行分隔符:$

字段分隔符:空白

模式

地址定界

/pattern1/,/pattern2/

/pattern/

可以 ! 取反

expression

表达式;&gt;, &gt;=, &lt;, &lt;=, ==, !=, ~

BEGIN{}

在遍历操作开始之前执行一次

END{}

在遍历操作结束之后、命令退出之前执行一次

<code>[Linux85]</code><code>#awk '/^soul/{print $0}' /etc/passwd /etc/shadow /etc/group</code>

<code>soul:x:</code><code>501</code><code>:</code><code>501</code><code>::</code><code>/</code><code>home</code><code>/</code><code>soul:</code><code>/</code><code>bin</code><code>/</code><code>bash</code>

<code>soul:!!:</code><code>16166</code><code>:</code><code>0</code><code>:</code><code>99999</code><code>:</code><code>7</code><code>:::</code>

<code>soul:x:</code><code>501</code><code>:</code>

<code>[Linux85]</code><code>#</code>

<code>#ID号大于等于500的用户</code>

<code>[Linux85]</code><code>#awk -F : '$3&gt;=500{print $1}' /etc/passwd</code>

<code>nfsnobody</code>

<code>gentoo</code>

<code>soul</code>

<code>BEGIN执行前操作</code>

<code>[Linux85]</code><code>#awk -F : 'BEGIN{print "UserName\n***********"}$3&gt;=500{print $1}' /etc/passwd</code>

<code>UserName</code>

<code>*</code><code>*</code><code>*</code><code>*</code><code>*</code><code>*</code><code>*</code><code>*</code><code>*</code><code>*</code><code>*</code>

awk的内置变量:

NF

字段数( The number of fields in the current input record.)

FS

field separator,读取文本时,所使用字段分隔符

RS

Record separator,输入文本信息所使用的换行符;

OFS

输出时使用字段分隔符,默认为空白(output field separator)

ORS

output record separator

<code>[Linux85]</code><code>#awk -F : '/^soul/{print $1,$7}' /etc/passwd</code>

<code>soul </code><code>/</code><code>bin</code><code>/</code><code>bash</code>

<code>                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                             </code> 

<code>[Linux85]</code><code>#awk 'BEGIN{FS=":"}/^soul/{print $1,$7}' /etc/passwd</code>

<code>[Linux85]</code><code>#awk 'BEGIN{FS=":";OFS=":"}/^soul/{print $1,$7}' /etc/passwd</code>

<code>soul:</code><code>/</code><code>bin</code><code>/</code><code>bash</code>

12

13

14

15

<code>[Linux85]</code><code>#awk '!/^$|^#/{print $1}' /etc/sysctl.conf</code>

<code>net.ipv4.ip_forward</code>

<code>net.ipv4.conf.default.rp_filter</code>

<code>net.ipv4.conf.default.accept_source_route</code>

<code>kernel.sysrq</code>

<code>kernel.core_uses_pid</code>

<code>net.ipv4.tcp_syncookies</code>

<code>net.bridge.bridge</code><code>-</code><code>nf</code><code>-</code><code>call</code><code>-</code><code>ip6tables</code>

<code>net.bridge.bridge</code><code>-</code><code>nf</code><code>-</code><code>call</code><code>-</code><code>iptables</code>

<code>net.bridge.bridge</code><code>-</code><code>nf</code><code>-</code><code>call</code><code>-</code><code>arptables</code>

<code>kernel.msgmnb</code>

<code>kernel.msgmax</code>

<code>kernel.shmmax</code>

<code>kernel.shmall</code>

<code>[Linux85]</code><code>#ifconfig | awk '/inet addr/{print $2}' | awk -F : '!/127/{print $2}'</code>

<code>172.16</code><code>.</code><code>251.85</code>

二、awk的进阶使用

1、print输出:print item1, item2, ...

各项目之间使用逗号隔开,而输出时则以空白字符分隔;

输出的item可以为字符串或数值、当前记录的字段(如$1)、变量或awk的表达式;数值会先转换为字符串,而后再输出;

print命令后面的item可以省略,此时其功能相当于print $0, 因此,如果想输出空白行,则需要使用print "";

2、printf输出:printf format, item1, item2, ...

其与print命令的最大不同是,printf需要指定format;

format用于指定后面的每个item的输出格式;

printf语句不会自动打印换行符;\n

format格式的指示符都以%开头;后面跟一个字符;

%c

显示字符的ASCII码;

%d | %i

十进制整数;

%e | %E

科学计数法显示数值;

%f

显示浮点数;

%g | %G

以科学计数法的格式或浮点数的格式显示数值;

%s

显示字符串;

%u

无符号整数;

%%

显示%自身;

<code>[Linux85]</code><code>#awk 'BEGIN{num1=20;num2=30; printf "%d %d\n",num1,num2}'</code>

<code>20</code> <code>30</code>

<code>#不显示item;只显示的是格式;格式对应的后面的变量;所以需要一一对应</code>

修饰符

N

显示宽度

-

左对齐

+

显示数值符号;正负数

<code>[Linux85]</code><code>#awk -F: '{printf "%-14s %s\n",$1,$NF}' /etc/passwd</code>

<code>root           </code><code>/</code><code>bin</code><code>/</code><code>bash</code>

<code>bin</code>            <code>/</code><code>sbin</code><code>/</code><code>nologin</code>

<code>daemon         </code><code>/</code><code>sbin</code><code>/</code><code>nologin</code>

<code>adm            </code><code>/</code><code>sbin</code><code>/</code><code>nologin</code>

<code>lp             </code><code>/</code><code>sbin</code><code>/</code><code>nologin</code>

<code>sync           </code><code>/</code><code>bin</code><code>/</code><code>sync</code>

3、awk内置变量之数据变量

NR

The number of input records,awk命令所处理的记录数;如果有多个文件,这个数目会把处理的多个文件中行统一计数;

Number of Field,当前记录的field个数;

FNR

与NR不同的是,FNR用于记录正处理的行是当前这一文件中被总共处理的行数;

ARGV

数组,保存命令行本身这个字符串,如awk '{print $0}' a.txt b.txt这个命令中,ARGV[0]保存awk,ARGV[1]保存a.txt;

ARGC

awk命令的参数的个数;

FILENAME

awk命令所处理的文件的名称;

ENVIROM

当前shell环境变量及其值的关联数组;

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

32

33

34

35

36

37

<code>[Linux85]</code><code>#awk '{print NR,$0}' 1.txt</code>

<code>1</code> <code>one line</code>

<code>2</code> <code>two line</code>

<code>3</code> <code>three line</code>

<code>4</code> <code>four line</code>

<code>5</code> <code>five line</code>

<code>[Linux85]</code><code>#awk '{print NR,$0}' 2.txt</code>

<code>1</code> <code>six line</code>

<code>2</code> <code>seven line</code>

<code>3</code> <code>eight line</code>

<code>4</code> <code>nine line</code>

<code>5</code> <code>ten line</code>

<code>[Linux85]</code><code>#awk '{print NR,$0}' 1.txt 2.txt</code>

<code>6</code> <code>six line</code>

<code>7</code> <code>seven line</code>

<code>8</code> <code>eight line</code>

<code>9</code> <code>nine line</code>

<code>10</code> <code>ten line</code>

<code>#</code>

<code>[Linux85]</code><code>#awk '{print FNR,$0}' 1.txt 2.txt</code>

<code>[Linux85]</code><code>#awk -F: '/root/{print $1,"is a user in",ARGV[1]}' /etc/passwd</code>

<code>root </code><code>is</code> <code>a user </code><code>in</code> <code>/</code><code>etc</code><code>/</code><code>passwd</code>

<code>operator </code><code>is</code> <code>a user </code><code>in</code> <code>/</code><code>etc</code><code>/</code><code>passwd</code>

<code>[Linux85]#awk </code><code>'BEGIN{print ARGC}'</code> <code>/etc/passwd /etc/group /etc/shadow</code>

<code>4</code>

<code>[Linux85]#</code>

<code># </code><code>'BEGIN{print ARGC}'</code><code>本身也当成一个参数</code>

<code>[Linux85]</code><code>#awk '{print $0,"in",  FILENAME}' 1.txt 2.txt</code>

<code>one line </code><code>in</code> <code>1</code><code>.txt</code>

<code>two line </code><code>in</code> <code>1</code><code>.txt</code>

<code>three line </code><code>in</code> <code>1</code><code>.txt</code>

<code>four line </code><code>in</code> <code>1</code><code>.txt</code>

<code>five line  </code><code>in</code> <code>1</code><code>.txt</code>

<code>six line </code><code>in</code> <code>2</code><code>.txt</code>

<code>seven line </code><code>in</code> <code>2</code><code>.txt</code>

<code>eight line </code><code>in</code> <code>2</code><code>.txt</code>

<code>nine line </code><code>in</code> <code>2</code><code>.txt</code>

<code>ten line </code><code>in</code> <code>2</code><code>.txt</code>

4、输出重定向

print items &gt; output-file

print items &gt;&gt; output-file

print items | command

特殊文件描述符:

/dev/stdin:标准输入

/dev/sdtout: 标准输出

/dev/stderr: 错误输出

/dev/fd/N: 某特定文件描述符,如/dev/stdin就相当于/dev/fd/0;

5、awk的操作符

算术操作符

赋值操作符

比较操作符

-x:负值

=:应[=]

x &lt; y   True if x is less than y.

+x:转换为数值

+=

x &lt;= y  True if x is less than or equal to y.

x^y:次方

-=

x &gt; y   True if x is greater than y.

x**y:次方

*=

x &gt;= y  True if x is greater than or equal to y.

x*y

/=

x == y  True if x is equal to y.

x/y

%=

x != y  True if x is not equal to y.

x+y

^=

x ~ y   True if the string x matches the regexp denoted by y.

x-y

**=

x !~ y  True if the string x does not match the regexp denoted by y.

x%y

++

subscript in array  True if the array array has an element with the subscript subscript.

--

awk中;任何非0值或非空字符串都为真;反之为假。

条件表达式:

select?if-true-exp:if-false-exp

6、模式和常见的模式类型

模式:

awk 'program' input-file1 input-file2 ...

program:

pattern { action }

....

常见的模式:

Regexp

正则表达式,格式为/regular expression/

expresssion

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

Ranges

指定的匹配范围,格式为pat1,pat2

BEGIN/END

特殊模式,仅在awk命令执行前运行一次或结束前运行一次

Empty(空模式)

匹配任意输入行;

常见的Action

Expressions

Control statements

Compound statements

Input statements

Output statements

7、控制语句

if-else

   语法:if (condition) {then-body} else {[ else-body ]}

<code>[Linux85]</code><code>#awk -F : 'BEGIN{OFS=":"}{if ($3==0) {print $1,"Administrator";} else {print $1,"Common User"}}' /etc/passwd</code>

<code>root:Administrator</code>

<code>bin</code><code>:Common User</code>

<code>daemon:Common User</code>

<code>adm:Common User</code>

<code>lp:Common User</code>

<code>sync:Common User</code>

<code>shutdown:Common User</code>

<code>[Linux85]</code><code>#awk -F: '{if ($1=="root") printf "%-15s: %s\n",$1,"Admin";else printf "%-15s: %s\n",$1,"Common User"}' /etc/passwd</code>

<code>root           : Admin</code>

<code>bin</code>            <code>: Common User</code>

<code>daemon         : Common User</code>

<code>adm            : Common User</code>

<code>lp             : Common User</code>

<code>sync           : Common User</code>

<code>shutdown       : Common User</code>

<code>halt           : Common User</code>

<code>mail           : Common User</code>

<code>uucp           : Common User</code>

<code>operator       : Common User</code>

<code>games          : Common User</code>

<code>gopher         : Common User</code>

<code>ftp            : Common User</code>

<code>nobody         : Common User</code>

<code>dbus           : Common User</code>

<code>usbmuxd        : Common User</code>

<code>[Linux85]</code><code>#awk -F: -v sum=0 '{if ($3&gt;=500) sum++}END{print sum}' /etc/passwd</code>

<code>3</code>

<code>[Linux85]</code><code>#统计uid&gt;=500的用户个数</code>

while

   语法:while (condition){statement1; statment2; ...}

<code>[Linux85]</code><code>#awk -F : '{i=1;while (i&lt;=3) {print $i;i++}}' /etc/passwd</code>

<code>root</code>

<code>x</code>

<code>0</code>

<code>bin</code>

<code>1</code>

<code>#打印出/etc/passwd前三个字段</code>

<code>[Linux85]</code><code>#awk -F: '{i=1;while (i&lt;=NF) { if (length($i)&gt;=4) {print $i}; i++ }}' /etc/passwd</code>

<code>/</code><code>root</code>

<code>/</code><code>bin</code><code>/</code><code>bash</code>

<code>/</code><code>bin</code>

<code>/</code><code>sbin</code><code>/</code><code>nologin</code>

do-while 至少执行一次循环体,不管条件满足与否

   语法:do {statement1, statement2, ...} while (condition)

<code>[Linux85]</code><code>#awk -F: '{i=1;do {print $i;i++}while(i&lt;=3)}' /etc/passwd</code>

<code>daemon</code>

<code>2</code>

<code>[Linux85]</code><code>#awk -F: '{i=4;do {print $i;i--}while(i&gt;4)}' /etc/passwd</code>

<code>7</code>

<code>12</code>

for

   语法:for (variable assignment; condition; iteration process) {statement1, statement2, ...}

<code>[Linux85]</code><code>#awk -F: '{for(i=1;i&lt;=3;i++) if (i&lt;3){printf "%s:",$i} print $i}' /etc/passwd</code>

<code>root:x:</code><code>0</code>

<code>bin</code><code>:x:</code><code>1</code>

<code>daemon:x:</code><code>2</code>

<code>adm:x:</code><code>4</code>

<code>lp:x:</code><code>7</code>

<code>sync:x:</code><code>0</code>

<code>shutdown:x:</code><code>0</code>

for循环遍历数组元素

   语法: for (i in array) {statement1, statement2, ...}

<code>[Linux85]</code><code>#awk -F: '$NF!~/^$/{BASH[$NF]++}END{for(A in BASH){printf "%15s:%i\n",A,BASH[A]}}' /etc/passwd</code>

<code> </code><code>/</code><code>sbin</code><code>/</code><code>shutdown:</code><code>1</code>

<code>       </code><code>/</code><code>bin</code><code>/</code><code>csh:</code><code>1</code>

<code>      </code><code>/</code><code>bin</code><code>/</code><code>bash:</code><code>2</code>

<code>  </code><code>/</code><code>sbin</code><code>/</code><code>nologin:</code><code>29</code>

<code>     </code><code>/</code><code>sbin</code><code>/</code><code>halt:</code><code>1</code>

<code>      </code><code>/</code><code>bin</code><code>/</code><code>sync:</code><code>1</code>

<code>#统计最后一个字段出现的次数</code>

case

语法:switch (expression) { case VALUE or /REGEXP/: statement1, statement2,... default: statement1, ...}

break 和 continue

next

提前结束对本行文本的处理,并接着处理下一行;

<code>[Linux85]</code><code>#awk -F: '{if($3%2==0) next;print $1,$3}' /etc/passwd</code>

<code>bin</code> <code>1</code>

<code>adm </code><code>3</code>

<code>sync </code><code>5</code>

<code>halt </code><code>7</code>

<code>operator </code><code>11</code>

<code>gopher </code><code>13</code>

<code>nobody </code><code>99</code>

<code>dbus </code><code>81</code>

<code>usbmuxd </code><code>113</code>

<code>vcsa </code><code>69</code>

<code>rtkit </code><code>499</code>

<code>abrt </code><code>173</code>

<code>postfix </code><code>89</code>

<code>rpcuser </code><code>29</code>

<code>pulse </code><code>497</code>

<code>soul </code><code>501</code>

8、数组

array[index-expression]

index-expression可以使用任意字符串;需要注意的是,如果某数据组元素事先不存在,那么在引用其时,awk会自动创建此元素并初始化为空串;因此,要判断某数据组中是否存在某元素,需要使用index in array的方式。

要遍历数组中的每一个元素,需要使用如下的特殊结构:

   for (var in array) { statement1, ... }

   其中,var用于引用数组下标,而不是元素值;

删除数组中的变量:delete  array[index]

<code>[Linux85]</code><code>#netstat -ant | awk '/^tcp/ {++S[$NF]} END {for(a in S) print a, S[a]}'</code>

<code>ESTABLISHED </code><code>2</code>

<code>LISTEN </code><code>10</code>

9、awk的内置函数

split(string, array [, fieldsep [, seps ] ])

将string表示的字符串以fieldsep为分隔符进行分隔,并将分隔后的结果保存至array为名的数组中;数组下标为从1开始的序列;

<code>[Linux85]</code><code>#df -lh | awk '!/^File/{split($5,percent,"%");if(percent[1]&gt;=10){print $1}}'</code>

<code>/</code><code>dev</code><code>/</code><code>sda1</code>

<code>/</code><code>dev</code><code>/</code><code>mapper</code><code>/</code><code>vg0</code><code>-</code><code>usr</code>

<code>#磁盘使用率大于等于%10的显示出来</code>

length([string]):返回string字符串中字符的个数;

<code>[Linux85]</code><code>#awk -F: '{for(i=1;i&lt;=NF;i++) { if (length($i)&gt;=4) {print $i}}}' /etc/passwd</code>

<code>/</code><code>sbin</code>

substr(string, start [, length ])

取string字符串中的子串,从start开始,取length个;start从1开始计数;

system(command):执行系统command并将结果返回至awk命令

systime():取系统当前时间

tolower(s):将s中的所有字母转为小写

toupper(s):将s中的所有字母转为大写

10、用户自定义函数

自定义函数使用function关键字。格式如下:

function F_NAME([variable])

{

statements

}

example:

<code>#统计当前系统上每个客户端IP的连接中状处于ESTABLISHED的连接态的个数;</code>

<code>[Linux85]</code><code>#netstat -tn | awk '/ESTABLISHED\&gt;/{split($5,ip,":");num[ip[1]]++}END{for (i in num) printf "%s %d\n", i, num[i]}'</code>

<code>172.16</code><code>.</code><code>254.28</code> <code>2</code>

<code>#统计ps aux命令执行时,当前系统上各状态的进程的个数;</code>

<code>[Linux85]</code><code>#ps aux | awk '!/^USER/{state[$8]++}END{for (i in state) printf "%s %d\n",i,state[i]}'</code>

<code>S&lt; </code><code>2</code>

<code>S&lt;sl </code><code>1</code>

<code>Ss </code><code>18</code>

<code>SN </code><code>1</code>

<code>S </code><code>69</code>

<code>Ss</code><code>+</code> <code>6</code>

<code>Ssl </code><code>2</code>

<code>R</code><code>+</code> <code>1</code>

<code>S</code><code>+</code> <code>2</code>

<code>Sl </code><code>2</code>

<code>S&lt;s </code><code>1</code>

<code>#统计ps aux命令执行时,当前系统上各用户的进程的个数;</code>

<code>[Linux85]</code><code>#ps aux | awk '!/^USER/{state[$1]++}END{for (i in state) printf "%s %d\n",i,state[i]}'</code>

<code>rpc </code><code>1</code>

<code>dbus </code><code>1</code>

<code>68</code> <code>2</code>

<code>postfix </code><code>2</code>

<code>rpcuser </code><code>1</code>

<code>root </code><code>96</code>

<code>gentoo </code><code>2</code>

<code>#显示ps aux命令执行时,当前系统上其VSZ(虚拟内存集)大于10000的进程及其PID;</code>

<code>[Linux85]</code><code>#ps aux | awk '!/USER/{if($5&gt;10000) print $2,$11}'</code>

<code>1</code> <code>/</code><code>sbin</code><code>/</code><code>init</code>

<code>397</code> <code>/</code><code>sbin</code><code>/</code><code>udevd</code>

<code>1184</code> <code>auditd</code>

<code>1209</code> <code>/</code><code>sbin</code><code>/</code><code>rsyslogd</code>

<code>1251</code> <code>rpcbind</code>

<code>1282</code> <code>dbus</code><code>-</code><code>daemon</code>

<code>1292</code> <code>NetworkManager</code>

<code>1297</code> <code>/</code><code>usr</code><code>/</code><code>sbin</code><code>/</code><code>modem</code><code>-</code><code>manager</code>

<code>1311</code> <code>rpc.statd</code>

<code>1344</code> <code>cupsd</code>

<code>1354</code> <code>/</code><code>usr</code><code>/</code><code>sbin</code><code>/</code><code>wpa_supplicant</code>

<code>1392</code> <code>hald</code>

<code></code>

本文转自Mr_陈 51CTO博客,原文链接:http://blog.51cto.com/chenpipi/1391178,如需转载请自行联系原作者