Shell编程之awk

目录

1.awk

1.1 什么是awk

1.2 awk的工作流程

1.3 awk程序执行方式

1.4 awk基本语法

1.4.1 awk的输出

1.4.2 awk的变量

1.4.3 awk操作符

1.4.4 awk的模式

1.4.5 awk控制语句

1.5 awk实验

 实验一:获取根分区剩余大小

 实验二:获取当前机器ip地址

 实验三:统计出apache的access.log中访问量最多的5个IP

 实验四:打印/etc/passwd中UID大于500的用户名和uid

 实验五:/etc/passwd 中匹配包含root或net或ucp的任意行

 实验六: 请打印出/etc/passwd 第一个域,并且在第一个域所有的内容前面加上“用户 

                帐号:”

 实验七:请打印出/etc/passwd 第三个域和第四个域

 实验八: 请打印第一域,并且打印头部信息为:这个是系统用户,打印尾部信息

                为:"================"

 实验九: 请打印出第一域匹配daemon的信息

 实验十: 请将/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的输出

1print 的使用格式
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
2printf 命令的使用格式:
虽然大多数情况下 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-file
print items >> output-file
print 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 是一种编程语言环境,因此,它也支持常用的运算符以及表达式,例如算术运算、逻辑运算以
及关系运算等。
1awk 支持常用的算术运算,这一点与其他的程序设计语言基本相同。
运算符说明举例
+加法运算
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

(5BEGIN模式

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
6END模式
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 等。掌握这些基本的流程控制语句,对于编写出结构良好的程
序非常重要。
1if 语句的功能是根据用户指定的条件来决定执行程序的哪个分支,其语法如下:
if (expression) {
    statement1
    statement2
else {
    statement3
    statement4
[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
2while 语句是另外一种常用的循环结构,其语法如下:
while (expression) {
           statement1          
           statement2      
           ……
}
当表达式 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
3awk还支持另外一种while 循环语句,其语法如下:
do {
      statement1
      statement2
      ...
}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
4for语句
for 循环语句通常用在循环次数已知的场合中,其语法如下:
for(expression1; expression2; expression3)
{
statement1
statement2
...
}
在上面的语法中,表达式 expression1 通常用来初始化循环变量,表达式 expression2 通常用来指定
循环执行的条件,表达式expression3 通常用来改变循环变量的值。当表达式 expression2 的值为真
时,执行循环体中的语句。
5break语句
用户可以通过使用break 语句在适当的时机退出 for 以及 while 等循环结构,而不必等到循环结构自己
退出。
6continue语句
continue 语句的主要功能是跳过循环结构中该语句后面的尚未执行的语句。 break 语句与 continue
句的功能有着明显的区别,前者是直接退出循环结构,而后者是跳过循环体中尚未执行的语句,重
新执行下一次循环。
7next语句
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
8exit语句
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

a7a8a839697f2969edd5a5a783ffd13b.png

实验九: 请打印出第一域匹配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

 

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值