一、基础用法
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
表达式;>, >=, <, <=, ==, !=, ~
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>=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>=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 > output-file
print items >> output-file
print items | command
特殊文件描述符:
/dev/stdin:标准输入
/dev/sdtout: 标准输出
/dev/stderr: 错误输出
/dev/fd/N: 某特定文件描述符,如/dev/stdin就相当于/dev/fd/0;
5、awk的操作符
算术操作符
赋值操作符
比较操作符
-x:负值
=:应[=]
x < y True if x is less than y.
+x:转换为数值
+=
x <= y True if x is less than or equal to y.
x^y:次方
-=
x > y True if x is greater than y.
x**y:次方
*=
x >= 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>=500) sum++}END{print sum}' /etc/passwd</code>
<code>3</code>
<code>[Linux85]</code><code>#统计uid>=500的用户个数</code>
while
语法:while (condition){statement1; statment2; ...}
<code>[Linux85]</code><code>#awk -F : '{i=1;while (i<=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<=NF) { if (length($i)>=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<=3)}' /etc/passwd</code>
<code>daemon</code>
<code>2</code>
<code>[Linux85]</code><code>#awk -F: '{i=4;do {print $i;i--}while(i>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<=3;i++) if (i<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]>=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<=NF;i++) { if (length($i)>=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\>/{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< </code><code>2</code>
<code>S<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<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>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,如需转载请自行联系原作者