一篇完整教会shell三剑客----awk

目录

  • 1. 什么是awk
  • 2. awk的工作流程
  • 3.awk程序的执行方式
  • 4. 基本语法
    • 4.1 awk的输出
    • 4.2 awk的变量
  • 5.awk操作符
  • 6.awk的模式
  • 7.awk控制语句
  • 8.awk中内置函数的使用

1. 什么是awk

awk是Linux以及UNIX环境中现有的功能最强大的数据处理工具。简单地讲,awk是一种处理文本数据的编程语言。awk的设计使得它非常适合于处理由行和列组成的文本数据。而在Linux或者UNIX环境中,这种类型的数据是非常普遍的。除此之外,awk 还是一种编程语言环境,它提供了正则表达式的匹配,流程控制,运算符,表达式,变量以及函数等一系列的程序设计语言所具备的特性。它从C语言中获取了一些优秀的思想。awk程序可以读取文本文件,对数据进行排序,对其中的数值执行计算以及生成报表等。

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)的操作。

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为要处理的文本数据文件。

4. 基本语法

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

4.1 awk的输出

(1)print的使用格式: print item1,item2,...
(2)printf命令的使用格式: 虽然大多数情况下awk的print语句可以完成任务,但有时我们还需要对格式做更多的控制。awk提供了printf函数来实现字符串的格式化。这个函数的功能和语法与C语言中的printf()函数基本相同,如下:printf(format, [arguments])
(3)输出重定向
print items > output-file
print items >> output-file
print items | command

练习:awk打印一个内容和打印多个内容,
格式化输出:显示Hello World字符串且宽度为50,向左对齐

[root@localhost day8]# cat hello.txt 
Hello World!
[root@localhost day8]# awk '{printf "%-50s",$0}' hello.txt
Hello World!                                      [root@localhost day8]# 
[root@localhost day8]#

4.2 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用于记录正处理的行是当前这一文件中被总共处理的行数;
FILENAME 表示正在处理的数据文件的名称
FS 输入字段分隔符,默认值是空格或者制表符,可使用-F指定分隔符
OFS 输出字段分隔符 ,OFS=”#”指定输出分割符为#。
RS 记录分隔符,默认值是换行符 \n
ENVIRON 当前shell环境变量及其值的关联数组;

示例:

[root@localhost day8]# echo 'hello china' > hello.txt 
[root@localhost day8]# cat hello.txt 
hello china
[root@localhost day8]# awk 'BEGIN {OFS="#"} {print $1,$2,"hello","world"}' hello.txt 
hello#china#hello#world
[root@localhost day8]#

(2) 用户自定义变量 awk允许用户自定义自己的变量以便在程序代码中使用,变量名命名规则与大多数编程语言相同,只能使用字母、数字和下划线,且不能以数字开头。awk变量名称区分字符大小写。
1、在awk中给变量赋值使用赋值语句进行
示例:

[root@localhost day8]# awk 'BEGIN{hello="world";print hello}'
world

2、在命令行中使用赋值变量 awk命令也可以在“脚本”外为变量赋值,并在脚本中进行引用。例如,上述的例子还可以改写为:

[root@localhost day8]# awk -v hello="world" 'BEGIN {print hello}'
world

5.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次方

示例:awk执行数学计算: 10/2*3+5%2+2^3

[root@localhost day8]# awk 'BEGIN{print 10/2*3+5%2+2^3}'
24

(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。

(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还支持其他的一些运算符,例如正号+、负号-、自增++以及自减–等,这些运算符的使用方法与其他的语言的使用方法完全相同。

示例:

[root@localhost day8]# cat hello.txt 
hello china
chongqing
chengdu
yunnan
shanxi
  1. awk处理文本:要求文本有5行内容,且当行数为奇数的时候打印第一个字段
[root@localhost day8]# awk '{ if (NR%2==1 && "END {print NR}==5") print $1}' hello.txt 
hello
chengdu
shanxi
[root@localhost day8]#
  1. awk处理文本: 要求文本有5行内容, 当行数不为3时打印第一个字段
[root@localhost day8]# awk '{ if (NR!=3 && "END {print NR}==5") print $1}' hello.txt
hello
chongqing
yunnan
shanxi
[root@localhost day8]#

6.awk的模式

awk的基本语法:
awk [options] 'PATTERN { action }' file1 file2, ...

在awk中,匹配模式处于非常重要的地位,它决定着匹配模式后面的操作会影响到哪些文本行。awk中的匹配模式主要包括关系表达式、正则表达式、混合模式,BEGIN模式以及END模式等。
(1)关系表达式awk提供了许多关系运算符,例如大于>、小于<或者等于==等。awk允许用户使用关系表达式作为匹配模式,当某个文本行满足关系表达式时,将会执行相应的操作。
(2)正则表达式awk支持以正则表达式作为匹配模式,与sed一样,用户需要将正则表达式放在两条斜线之间,其基本语法如下:```/regular_expression/````
(3)混合模式awk不仅支持单个的关系表达式或者正则表达式作为模式,还支持使用逻辑运算符&&、||或者!将多个表达式组合起来作为一个模式。其中,&&表示逻辑与,||表示逻辑或,!表示逻辑非。
(4)区间模式awk还支持一种区间模式,也就是说通过模式可以匹配一段连续的文本行。区间模式的语法如下:pattern1, pattern2其中,pattern1和pattern2都是前面所讲的匹配模式,可以是关系表达式,也可以是正则表达式等。当然,也可以是这些模式的混合形式。
(5)BEGIN模式BEGIN模式是一种特殊的内置模式,其成立的时机为awk程序刚开始执行,但是又尚未读取任何数据之前。因此,该模式所对应的操作仅仅被执行一次,当awk读取数据之后,BEGIN模式便不再成立。所以,用户可以将与数据文件无关,而且在整个程序的生命周期中,只需执行1次的代码放在BEGIN模式对应的操作中。
(6)END模式END模式是awk的另外一种特殊模式,该模式成立的时机与BEGIN模式恰好相反,它是在awk命令处理完所有的数据,即将退出程序时成立,在此之前,END模式并不成立。无论数据文件中包含多少行数据,在整个程序的生命周期中,该模式所对应的操作只被执行1次。因此,一般情况下,用户可以将许多善后工作放在END模式对应的操作中。
示例:

[root@localhost day8]# cat sorce.txt 
zhangsan 80
lisi 92
wangwu 60
zhaoliu 76
[root@localhost day8]# awk '$2 > 80 {print}' sorce.txt 
lisi 92
[root@localhost day8]# awk '/^l/{print}' sorce.txt 
lisi 92
[root@localhost day8]# awk '/^l/ && $2>80 {print}' sorce.txt 
lisi 92
[root@localhost day8]# awk '/^l/,$2==90 {print}' sorce.txt 
lisi 92
wangwu 60
zhaoliu 76
[root@localhost day8]# 

7.awk控制语句

作为一种程序设计语言,awk支持程序的流程控制,例如条件判断、循环以及其他的一些流程控制语句,例如continue、break以及exit等。
(1)if语句的功能是根据用户指定的条件来决定执行程序的哪个分支,其语法如下:

if (expression)
 { 
 	statement1 
 	statement2
 	}
 	else
 	{ 
 	statement3
 	 statement4
 	 }

示例:

  1. if: 给定一个成绩0-100,输出等级: A:85-100, B:70-84, C:60-69, D:0-59
{
 
if ($1  >= 85 && $1 <= 100){
    print $1,"A"
}
else 
{
    if ($1 >= 70 && $1<=84){
        print $1,"B"
    }
    else
    {
        if ($1 >= 60 && $1 <=69){
            print $1,"C"
        }
        else
        {
            if ($1 >=0 && $1 <= 59){
                print $1,"D"
            }
            else
            {
                print  $1  " Tips:invalue  scores "
            }
        }
    }
}
[root@localhost day8]#   chmod a+x awk_if.sh
[root@localhost day8]#  ./awk_if.sh score.txt 
55 D
120 Tips:invalue  scores
76 B
92 A

(2)for语句for循环语句
通常用在循环次数已知的场合中,其语法如下:

for(expression1; expression2; expression3)
{
 statement1 
 statement2
  ...
}

在上面的语法中,表达式expression1通常用来初始化循环变量,表达式expression2通常用来指定循环执行的条件,表达式expression3通常用来改变循环变量的值。当表达式expression2的值为真时,执行循环体中的语句。
示例:
2. for(): 计算1+2…+100的和

BEGIN{
sum=0
for(i=1;i<=100;i++){
    sum+=i
}
print "1+2+....+100="sum
}
 
[root@localhost day8]#  ./awk_for.sh 
1+2+....+100=5050

for循环还可以用来遍历数组元素:
语法: for(变量 in 数组){语句}
示例:
3. for(in): 定义一个数组:数组中的元素为: array[name]=age,-> zhangsan:18 lisi:20 wangwu=21
循环访问数组,并输出数组中的key和value

[root@localhost day8]#  vim awk_array.sh
#!/bin/awk -f
BEGIN{
array["zhangsan"]=18
array["lisi"]=20
array["wangwu"]=21
for(var in array){
    print var,array[var]
  }
}                                                
[root@localhost test]# ./awk_array.sh 
zhangsan 18
wangwu 21
lisi 20

(3)while语句是另外一种常用的循环结构,其语法如下:

while (expression)
{
statement1 
statement2
...
 }

当表达式expression的值为真时,执行循环体中的statement1以及statement2等语句。如果循环体中只包含一条语句,则可以省略大括号。

(4)awk还支持另外一种while循环语句,其语法如下:

do 
{
 statement1 
 statement2 
 ...
 }
 while (expression)

同样,当表达式expression的值为真时执行循环体中的语句。

示例:
4. 用while和do…while实现9*9乘法表

[root@localhost day8]#  vim do_while_awk.sh
#!/bin/awk -f
BEGIN {  
i=1     
    do
    {        
        j=1 
        do
        {
            printf("%d*%d=%d\t",i,j,i*j)
            j++
        }while(j<=i)
      i++
      printf("\n") 
    }while (i<=9)
}
[root@localhost day8]#  chmod a+x do_while_awk.sh
[root@localhost day8]# ./do_while_awk.sh 
1*1=1	
2*1=2	2*2=4	
3*1=3	3*2=6	3*3=9	
4*1=4	4*2=8	4*3=12	4*4=16	
5*1=5	5*2=10	5*3=15	5*4=20	5*5=25	
6*1=6	6*2=12	6*3=18	6*4=24	6*5=30	6*6=36	
7*1=7	7*2=14	7*3=21	7*4=28	7*5=35	7*6=42	7*7=49	
8*1=8	8*2=16	8*3=24	8*4=32	8*5=40	8*6=48	8*7=56	8*8=64	
9*1=9	9*2=18	9*3=27	9*4=36	9*5=45	9*6=54	9*7=63	9*8=72	9*9=81

8.awk中内置函数的使用

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

[root@localhost day8]# date +%T | awk '{split($0,a,":");print a[1],a[2],a[3]}'
14 16 46

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

[root@localhost day8]# awk 'BEGIN{print length("helloworld")}'
10

(3)substr(string, start [, length])功能:取string字符串中的子串,从start开始,取length个;start从1开始计数;

[root@localhost day8]# awk 'BEGIN{print substr("helloworld",u,6)}'
hellow

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

[root@localhost day8]# awk 'BEGIN{print system ("whoami")}'
root
0

(5)systime()功能:取系统当前时间

[root@localhost day8]# awk 'BEGIN{print systime()}'
1662099577

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

[root@localhost day8]# awk 'BEGIN{print tolower("HELLOWORLD")}'
helloworld

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

[root@localhost day8]# awk 'BEGIN{print toupper("HELLOworld")}'
HELLOWORLD

你可能感兴趣的:(shell,unix,linux,服务器)