目录
实验三:统计出apache的access.log中访问量最多的5个IP
实验四:打印/etc/passwd中UID大于500的用户名和uid
实验五:/etc/passwd 中匹配包含root或net或ucp的任意行
实验六: 请打印出/etc/passwd 第一个域,并且在第一个域所有的内容前面加上“用户
实验八: 请打印第一域,并且打印头部信息为:这个是系统用户,打印尾部信息
实验十: 请将/etc/passwd 中的root替换成gongda,记住是临时替换输出屏幕看到效
实验十一:请同时匹配passwd文件中,带mail或bash的关键字的信息
1.awk
1.1 什么是awk
awk
是
Linux
以及
UNIX
环境中现有的功能最强大的数据处理工具。简单地讲,
awk
是一种处理文本
数据的编程语言。awk
的设计使得它非常适合于处理由行和列组成的文本数据。而在
Linux
或者
UNIX
环境中,这种类型的数据是非常普遍的。
除此之外,
awk
还是一种编程语言环境,它提供了正则表达式的匹配,流程控制,运算符,表达
式,变量以及函数等一系列的程序设计语言所具备的特性。它从C
语言中获取了一些优秀的思想。
awk
程序可以读取文本文件,对数据进行排序,对其中的数值执行计算以及生成报表等。
1.2 awk的工作流程
awk
命令的基本语法如下:
awk pattern { actions }
在上面的语法中,
pattern
表示匹配模式,
actions
表示要执行的操作。以上语法表示,当某个文本
行符合pattern
指定的匹配规则时,执行
actions
所执行的操作。在上面的语法中,
pattern
和
actions
都是可选的,但是两者必须保证至少有一个。如果省略匹配模式pattern
,则表示对所有的文本行执
行
actions
所表示的操作;如果省略actions
,则表示将匹配成功的行输出到屏幕。
对于初学者来说,搞清楚
awk
的工作流程非常重要。只有在掌握了
awk
的工作流程之后,才有可能
用好awk来处理数据。在
awk
处理数据时,它会反复执行以下
4
个步骤:
(
1
)自动从指定的数据文件中读取行文本。
(
2
)自动更新
awk
的内置系统变量的值,例如列数变量
NF
、行数变量
NR
、行变量
$0
以及各个列
变量$1、
$2
等等。
(
3
)依次执行程序中所有的匹配模式及其操作。
(
4
)当执行完程序中所有的匹配模式及其操作之后,如果数据文件中仍然还有未读取的数据
行,则返回到第(1)步,重复执行(1
)
~
(
4
)的操作。
1.3 awk程序执行方式
1.通过命令行执行awk
程序,语法如下:
awk 'program-text' datafile
2.执行awk脚本
在
awk
程序语句比较多的情况下,用户可以将所有的语句写在一个脚本文件中,然后通过
awk
命令
来解释并执行其中的语句。awk
调用脚本的语法如下:
awk -f program-file file ..
在上面的语法中,
-f
选项表示从脚本文件中读取
awk
程序语句,
program-file
表示
awk
脚本文件名
称,
file表示要处理的数据文件。
3.可执行脚本文件
在上面介绍的两种方式中,用户都需要输入awk命令才能执行程序。除此之外,用户还可以通过类
似于Shell脚本的方式来执行awk程序。在这种方式中,需要在awk程序中指定命令解释器,并且赋
予脚本文件的可执行权限。其中指定命令解释器的语法如下:
#!/bin/awk -f
以上语句必须位于脚本文件的第一行。然后用户就可以通过以下命令执行
awk
程序:
awk-script file
其中,
awk-script
为
awk
脚本文件名称,
file
为要处理的文本数据文件。
1.4 awk基本语法
awk [options] 'script' file1 file2, ...awk [options] 'PATTERN { action }' file1 file2, ...
1.4.1 awk的输出
(1)print
的使用格式:
print item1,item2,...
要点:
1
.
各项目之间使用逗号隔开,而输出时则以空白字符分隔;
2
.
输出的
item
可以为字符串或数值、当前记录的字段
(
如
$1
)
、变量或
awk
的表达式;数值会先转换
为字符串,而后再输出;
3
. print
命令后面的
item
可以省略,此时其功能相当于
print
$0
,
因此,如果想输出空白行,则
需要使用
print “”
;
示例:
[root@localhost ~]# awk 'BEGIN { print "line one\nline two\nline three"}'
line one
line two
line three
[root@localhost ~]# awk 'BEGIN{print "This","is","test"}'
This is test
[root@localhost ~]# awk -F: '{print $1,$3}' /etc/passwd | head -n 3
root 0
bin 1
daemon 2
(2)printf
命令的使用格式:
虽然大多数情况下
awk
的
print
语句可以完成任务,但有时我们还需要对格式做更多的控制。
awk
提
供了printf
函数来实现字符串的格式化。这个函数的功能和语法与
C
语言中的
printf()
函数基本相同,
如下:
printf(format, [arguments])
其中圆括号是可选的,第
1
个参数
format
是一个用来描述输出格式的字符串,通常以引号括起来的
字符串常量的形式提供。arguments
为一个参数列表,表示用来显示的数据,可以是变量名等,多
个参数之间用逗号隔开。参数列表的项是有顺序的,与前面的格式化字符串中的格式说明相对应。
printf
语句不会自动打印换行符。
1、
其与
print
命令的最大不同是,
printf
需要指定
format
;
2、
format
用于指定后面的每个
item
的输出格式;
3、
printf
语句不会自动打印换行符:
\n
format
格式的指示符都以
%
开头,后跟一个字符,如下:
%c |
显示字符的
ASCII
码
|
%d,%i |
十进制整数
|
%e,%E |
科学计数法显示数值
|
%f |
显示浮点数
|
%g,%G |
以科学计数法的格式或浮点数的格式显示数值
|
%s |
显示字符串
|
%u |
无符号整数
|
%% |
显示
%
自身
|
修饰符:
N | 显示宽度 |
- | 左对齐 |
+ | 显示数值符号 |
示例:
[root@localhost ~]# awk -F: '{printf "%-15s %i\n",$1,$3}' /etc/passwd |head -n 3
root 0
bin 1
daemon 2
(3)输出重定向
print items > output-fileprint items >> output-fileprint items | command
示例:
[root@localhost ~]# awk -F: '{printf "%-15s %i\n",$1,$3 > "test1" }' /etc/passwd
1.4.2 awk的变量
与其他的程序设计语言一样,
awk
本身支持变量的相关操作,包括变量的定义和引用,以及参与相
关的运算等。此外,还包含了许多内置的系统变量。
变量的作用是用来存储数据。变量由变量名和值两部分组成,其中变量名是用来实现变量值的引用
的途径,而变量值则是内存空间中存储的用户数据。
awk
的变量名只能包括字母、数字和下划线,并且不能以数字开头。例如
abc
、
a
、
z
以及
a123
都是
合法的变量名,而123abc
则是非法的变量名。另外,
awk
的变量名是区分大小写的,因此,
X
和
x
分别表示不同的变量。
在
awk
中定义变量的方法非常简单,只要给出一个变量名并且赋予适当的值即可。
awk
中的变量类
型分为两种,分别为字符串和数值。但是在定义awk
变量时,毋需指定变量类型,
awk
会根据变量
所处的环境自动判断。如果没有指定值,数值类型的变量的缺省值为0
,字符串类型的变量的缺省
值为空串。
awk
提供了许多非常实用的系统变量,例如字段变量、字段数变量以及记录数变量等。
(1) awk 内置变量
变量 | 说明 |
$0 |
记录变量,表示当前正在处理的记录
|
$n |
字段变量,其中
n
为整数,且
n
大于
1
。表示第
n
个字段的值
|
NF |
整数值,表示当前记录(变量
$0
所代表的记录)的字段数
|
NR |
整数值,表示
awk
已经读入的记录数;如果有多个文件,这个数目会把处理的多个文
件中行统一计数
|
FNR |
与
NR
不同的是,
FNR
用于记录正处理的行是当前这一文件中被总共处理的行数
|
RILENAM |
表示正在处理的数据文件的名称
|
FS |
输入字段分隔符,默认值是空格或者制表符,可使用
-F
指定分隔符
|
OFS |
输出字段分隔符 ,
OFS=”#”
指定输出分割符为
#
|
RS |
记录分隔符,默认值是换行符
\n
|
ENVIRON |
当前
shell
环境变量及其值的关联数组
|
示例:
[root@localhost ~]# echo "this is" > test.txt
[root@localhost ~]# awk 'BEGIN {OFS="#"} {print $1,$2,"a","test"}' test.txt
this#is#a#test
[root@localhost ~]# awk 'BEGIN{print ENVIRON["PATH"]}'
/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/root/bin
(2)用户自定义变量
awk
允许用户自定义自己的变量以便在程序代码中使用,变量名命名规则与大多数编程语言相同,
只能使用字母、数字和下划线,且不能以数字开头。awk
变量名称区分字符大小写。
1
、在
awk
中给变量赋值使用赋值语句进行
示例:
[root@localhost ~]# awk 'BEGIN{test="hello";print test}'
hello
2
、在命令行中使用赋值变量
awk
命令也可以在
“
脚本
”
外为变量赋值,并在脚本中进行引用。例如,上述的例子还可以改写为:
[root@localhost ~]# awk -v test="hello" 'BEGIN {print test}'
hello
1.4.3 awk操作符
awk
是一种编程语言环境,因此,它也支持常用的运算符以及表达式,例如算术运算、逻辑运算以
及关系运算等。
(1)awk
支持常用的算术运算,这一点与其他的程序设计语言基本相同。
运算符 | 说明 | 举例 |
+ | 加法运算 |
1+2
表示计算
1
和
2
的和
|
- | 减法运算 |
82-2
表示计算
82
和
2
的差
|
* | 乘法运算 |
2*5
表示计算
2
和
5
的积
|
/ | 除法运算 |
6/3
表示计算
6
和
2
的商
|
% | 求模运算 |
5/2
表示计算
5
除以
2
的余数
|
^ | 指数运算 |
2^3
表示计算
2
的
3
次方
|
示例:
[root@localhost ~]# awk 'BEGIN{x=2;y=3;print x**y,x^y,x*y,x/y,x+y,x-y,x%y}'
8 8 6 0.666667 5 -1 2
(2)赋值运算符
运算符 | 说明 | 举例 |
= |
赋值运算
|
x=5
表示将数值
5
赋给变量
x
|
+= |
复合赋值运算,表示将前后两个数值相加后
的和赋给前面的变量
|
x+=5
表示先将
x
的值与
5
相加,然后再将
和赋给变量
x
,等价于
x=x+5
|
-= |
复合赋值运算,表示将前后两个数值相减后
的值赋给前面的变量
|
x-=5
表示先将
x
的值减去
5
,然后再将得
到的差赋给变量
x
,等价于
x=x-5
|
*= |
复合赋值运算,表示前后两个数的乘积赋给
前面的变量
|
表示先将
x
的值乘以
5
,然后再将得到的
乘积赋给变量
x
|
/= |
复合赋值运算,表示前后两个数值的商赋给
前面的变量
|
表示先将变量
x
除以
5
,再将商赋给变量
x
|
%= |
复合赋值运算,表示将前面的数值除以后面
的数值所得的余数赋给前面的变量
|
将变量
x
与
5
相除后的余数赋给变量
x
|
^= |
复合运算符,表示将前面的数值的后面数值
次方赋给前面的变量
|
x^=3
表示将变量
x
的
3
次方赋给变量
x
|
(3) 条件运算符
awk
中的条件运算符只有一个,其语法如下:
expression?value1:value2
这是一个三目运算符,当表达式expression的值为真时,返回值为value1;否则,返回值为
value2。
示例:
[root@localhost ~]# cat file
3 6
10 9
3 3
[root@localhost ~]# awk '{max=$1>$2?$1:$2;print NR,"max=",max}' file
1 max= 6
2 max= 10
3 max= 3
(4)逻辑运算符
awk
支持
3
种逻辑运算,分别为逻辑与、逻辑或和逻辑非 .
运算符 | 说明 | 举例 |
&& |
逻辑与,当前后两个表达式的值全部为真时,其运算结果才为真
|
1>2&&3>2 的值为假
|
| | |
逻辑或,前后两个表达式只要有一个为真,则其运算结果为真。当两个表达式的值都为假时,其运算结果才为假
|
1>2||3>2 的值为真
|
! |
逻辑非,当表达式的值为真时,其运算结果为假;当表达式的值为假时,其运算结果为真
|
!(1>2)
的值为真
|
(5)关系运算符
运算符 | 说明 | 举例 |
> | 大于 |
5>2
的值为真
|
>= | 大于或者等于 |
8>=8
的值为真
|
< | 小于 |
8<12
的值为真
|
<= | 小于或者等于 |
4<=7
的值为真
|
== | 等于 |
9==9
的值为真
|
!= | 不等于 |
1!=3
的值为真
|
~ | 匹配运算符 |
$1 ~ /^T/
表示匹配第一个字段以字符
T
开头的记录
|
!~ | 不匹配运算符 |
$1 !~ /a/
表示匹配第一个字段不含有字符
a
的记录
|
(6)其他运算符
awk
还支持其他的一些运算符,例如正号
+
、负号
-
、自增
++
以及自减
--
等,这些运算符的使用方法
与其他的语言的使用方法完全相同。
1.4.4 awk的模式
awk 的基本语法:awk [options] 'PATTERN { action }' file1 file2, ...
在
awk
中,匹配模式处于非常重要的地位,它决定着匹配模式后面的操作会影响到哪些文本行。
awk
中的匹配模式主要包括关系表达式、正则表达式、混合模式,BEGIN
模式以及
END
模式等。
(1)关系表达式
awk
提供了许多关系运算符,例如大于>、小于<或者等于
==
等。
awk
允许用户使用关系表达式作
为匹配模式,当某个文本行满足关系表达式时,将会执行相应的操作。
[root@localhost test11]# cat file
liming 80
wangmei 70
zhangsan 90
lisi 81
[root@localhost test11]# awk '$2 > 80 {print}' file
zhangsan 90
lisi 81
(2)正则表达式
awk
支持以正则表达式作为匹配模式,与
sed
一样,用户需要将正则表达式放在两条斜线之间,其
基本语法如下:
/regular_expression/
[root@localhost test11]# awk '/^l/{print}' file
liming 80
lisi 81
[root@localhost test11]# awk '/^l|z/{print}' file
liming 80
zhangsan 90
lisi 81
(3)混合模式
awk
不仅支持单个的关系表达式或者正则表达式作为模式,还支持使用逻辑运算符
&&
、
||
或者
!
将多
个表达式组合起来作为一个模式。其中,&&
表示逻辑与,
||
表示逻辑或,!表示逻辑非。
[root@localhost test11]# awk '/^l/ && $2>80 {print}' file
lisi 81
(4)区间模式
awk
还支持一种区间模式,也就是说通过模式可以匹配一段连续的文本行。区间模式的语法如下:
pattern1, pattern2
其中,
pattern1
和
pattern2
都是前面所讲的匹配模式,可以是关系表达式,也可以是正则表达式
等。当然,也可以是这些模式的混合形式。
[root@localhost test11]# awk '/^liming/,$2==90 {print}' file
liming 80
wangmei 70
zhangsan 90
(5)BEGIN模式
BEGIN
模式是一种特殊的内置模式,其成立的时机为
awk
程序刚开始执行,但是又尚未读取任何数
据之前。因此,该模式所对应的操作仅仅被执行一次,当awk
读取数据之后,
BEGIN
模式便不再成
立。所以,用户可以将与数据文件无关,而且在整个程序的生命周期中,只需执行1
次的代码放在
BEGIN
模式对应的操作中。
[root@localhost test11]# cat 1.sh
#!/bin/awk -f
BEGIN {print "hello,world"}
[root@localhost test11]# ./1.sh
hello,world
[root@localhost ~]# awk -F: 'BEGIN{printf"%-15s%-3s%-15s\n","user","uid","shell"}$3==0,$7~"nologin"{printf"%-15s%-3s%-15s\n",$1,$3,$7}' /etc/passwd
(6)END模式
END
模式是
awk
的另外一种特殊模式,该模式成立的时机与
BEGIN
模式恰好相反,它是在
awk
命令
处理完所有的数据,即将退出程序时成立,在此之前,END
模式并不成立。无论数据文件中包含多
少行数据,在整个程序的生命周期中,该模式所对应的操作只被执行1
次。因此,一般情况下,用
户可以将许多善后工作放在END
模式对应的操作中。
[root@localhost test11]# cat 2.sh
#! /bin/awk -f
BEGIN {
print "scores report"
print "================================="
}
{ print }
END {
print "================================"
print "printing is over"
}
[root@localhost test11]# ./2.sh file
scores report
=================================
liming 80
wangmei 70
zhangsan 90
lisi 81
================================
printing is over
[root@localhost ~]# awk -F: 'BEGIN {printf "%-15s %-3s
%-15s\n","user","uid","shell"} $3==0,$7~"nologin" {printf "%-15s %-3s
%-15s\n",$1,$3,$7} END {print "-----End file-----"}' /etc/passwd
1.4.5 awk控制语句
作为一种程序设计语言,
awk
支持程序的流程控制,例如条件判断、循环以及其他的一些流程控制
语句,例如continue
、
break
以及
exit
等。掌握这些基本的流程控制语句,对于编写出结构良好的程
序非常重要。
(1)if
语句的功能是根据用户指定的条件来决定执行程序的哪个分支,其语法如下:
if (expression) {statement1statement2}else {statement3statement4}
[root@localhost test11]# cat 3.sh
#! /bin/awk -f
{
if ($2 >= 90) {
print $1,"A"
}
else{
if($2 >= 80 && $2 < 90){
print $1,"B"
}
else{
print $1,"C"
}
}
}
[root@localhost test11]# cat file
liming 80
wangmei 70
zhangsan 90
lisi 81
[root@localhost test11]# ./3.sh file
liming B
wangmei C
zhangsan A
lisi B
[root@localhost ~]# awk -F: '{if ($1=="root") printf "%-10s %-15s\n", $1,"Admin"; else printf "%-10s %-15s\n",$1, "Common User"}' /etc/passwd | head -n 3
[root@localhost ~]# awk '{if ($1>$2) print NR,"max =",$1;else print NR,"max=",$2}' file
(2)while
语句是另外一种常用的循环结构,其语法如下:
while (expression) {statement1statement2……}
当表达式
expression
的值为真时,执行循环体中的
statement1
以及
statement2
等语句。如果循环体
中只包含一条语句,则可以省略大括号。
[root@localhost ~]# awk 'BEGIN{while(i<=100) {sum+=i;i++}print "sum=",sum}'sum= 5050
[root@localhost test11]# cat 4.sh
#! /bin/awk -f
BEGIN {
i=0
while (++i <= 9){
print i^2
}
}
[root@localhost test11]# ./4.sh
1
4
9
16
25
36
49
64
81
(3)awk还支持另外一种while
循环语句,其语法如下:
do {statement1statement2...}while (expression)
同样,当表达式
expression
的值为真时执行循环体中的语句。
[root@localhost test11]# cat 5.sh
#! /bin/awk -f
BEGIN {
i=1
do{
print i^2
}while (++i<=9)
}
[root@localhost test11]# ./5.sh
1
4
9
16
25
36
49
64
81
(4)for语句
for
循环语句通常用在循环次数已知的场合中,其语法如下:
for(expression1; expression2; expression3){statement1statement2...}
在上面的语法中,表达式
expression1
通常用来初始化循环变量,表达式
expression2
通常用来指定
循环执行的条件,表达式expression3
通常用来改变循环变量的值。当表达式
expression2
的值为真
时,执行循环体中的语句。
(5)break语句
用户可以通过使用break
语句在适当的时机退出
for
以及
while
等循环结构,而不必等到循环结构自己
退出。
(6)continue语句
continue
语句的主要功能是跳过循环结构中该语句后面的尚未执行的语句。
break
语句与
continue
语
句的功能有着明显的区别,前者是直接退出循环结构,而后者是跳过循环体中尚未执行的语句,重
新执行下一次循环。
(7)next语句
next
语句的功能与
continue
语句非常相似,但是
next
语句并不是用在循环结构中,而是用在整个
awk
程序中。当awk
执行程序时,如果遇到
next
语句,则提前结束对本行文本的处理,
awk
会继续
读取下一行数据,并且从第一个模式及其操作开始执行。
例如,下面的命令将显示其ID号为奇数的用户:
[root@localhost ~]# awk -F: '{if($3%2==0) next;print $1,$3}' /etc/passwd|head -n 3
bin 1
adm 3
sync 5
(8)exit语句
exit
语句的功能是终止
awk
程序的执行。
1.5 awk实验
实验一:获取根分区剩余大小
[root@manager ~]# df -h / | tail -1 | awk '{print $4}'
实验二:获取当前机器ip地址
[root@manager ~]# ifconfig | awk 'NR==2{print $2}'
实验三:统计出apache的access.log中访问量最多的5个IP
[root@manager ~]# awk '{print $1}' access.log | sort | uniq -c | sort -nr | head -5
实验四:打印/etc/passwd中UID大于500的用户名和uid
[root@manager ~]# awk -F: 'BEGIN {printf "%10-s %5-s\n","USER","UID"} $3>500 {printf "%10-s %5-s\n",$1,$3}' /etc/passwd
实验五:/etc/passwd 中匹配包含root或net或ucp的任意行
[root@manager ~]# awk -F: '/^(root|net|ucp)/' /etc/passwd
实验六: 请打印出/etc/passwd 第一个域,并且在第一个域所有的内容前面加上“用户
帐号:”
[root@manager ~]# awk -F: '{print "用户账号: " $1}' /etc/passwd
实验七:请打印出/etc/passwd 第三个域和第四个域
[root@manager ~]# awk -F: '{printf"%-10s%-d\n",$3,$4}' /etc/passwd
实验八: 请打印第一域,并且打印头部信息为:这个是系统用户,打印尾部信息
为:"================"
[root@manager ~]# awk -F: 'BEGIN{print "这个是系统用户"}{print $1}END{print"================"}' /etc/passwd
实验九: 请打印出第一域匹配daemon的信息
[root@manager ~]# awk -F: '$1=="daemon"' /etc/passwd
实验十: 请将/etc/passwd 中的root替换成gongda,记住是临时替换输出屏幕看到效
果即可
[root@manager ~]# awk -F: 'gsub(/root/,"gongda"){print $0}' /etc/passwd
实验十一:请同时匹配passwd文件中,带mail或bash的关键字的信息
[root@manager ~]# awk -F: '$0~/root|mail/' /etc/passwd