第1章 三剑客基础入门

  要弄懂awk程序,必须熟悉了解这个工具的规则。本实战笔记的目的是通过实际案例或面试题带同学们熟练掌握awk在企业中的用法,而不是awk程序的帮助手册

1.1 awk简介

  一种名字怪异的语言

  模式扫描和处理

awk不仅仅时linux系统中的一个命令,而且是一种编程语言,可以用来处理数据和生成报告(excel)。处理的数据可以是一个或多个文件,可以是来自标准输入,也可以通过管道获取标准输入,awk可以在命令行上直接编辑命令进行操作,也可以编写成awk程序来进行更为复杂的运用。本章主要讲解awk命令的运用。

1.1 学完awk你可以掌握

  1. 记录与字段

  2. 模式匹配:模式与动作

  3. 基本的awk执行过程

  4. awk常用的内置变量(预定义变量)

  5. awk语法:循环,条件

  6. awk常用函数

  7. 向awk传递参数

  8. awk引用shell变量

  9. awk小程序及调试思路

 

1.2 awk的格式

  • awk指定是由模式,动作,或者模式和动作的组合组成

  • 模式pattern,可以类似理解成sed模式匹配,可以有表达式组成,也可以是两个正斜杠 / /直接的正则表达式。比如NR==1,这就是模式,可以把它理解为一个条件。

  • 动作action,是由大括号里面的一条或多条语句组成,语句直接使用分号隔开。比如awk使用格式:

三剑客老大之awk命令上篇_第1张图片

 

  • awk处理的内容可以来自标准输入< ,一个或多个文本文件或管道。



  • patter既模式,也可以理解成为条件,也叫找谁,你找谁?高矮,胖瘦,男女?都是条件,既模式。

  • action既动作,可以理解成干啥,找到人之后要做什么。

  • 模式和动作的详细介绍我们放在后面部分,现在大家要对awk结构有一个了解。

  •  

 三剑客老大之awk命令上篇_第2张图片

1.3 模式动作实战一

 

实例1-1         

将/etc/passwd 第2行到第6行 及行号打印出来?

[root@admin /]# awk -F : 'NR==2,NR==6{printNR,$1}' /etc/passwd

2 bin

3 daemon

4 adm

5 lp

6 sync

 

[root@admin /]# cat /etc/passwd | awk -F :'NR>=2&&NR<=6{print NR,$1}' 

2 bin

3 daemon

4 adm

5 lp

6 sync

 

命令说明:

-F 指定分隔符为冒号:相当于以“:” 为菜刀,进行字段(列)切割

NR==2行, 到 NR==6 这部分是表示模式,是一个条件,表示取第二行到第六行

NR>=2 && NR<=6   条件大于等于2行 并且 小于等于6行 

{pirnt NR,$1}    这部分表示动作,要干什么,表示要输出NR行号和$1第一列

 

1.3.2 只有模式(条件)

[root@admin /]# awk -F : 'NR>=2 &&NR<=6' /etc/passwd

bin:x:1:1:bin:/bin:/sbin/nologin

daemon:x:2:2:daemon:/sbin:/sbin/nologin

adm:x:3:4:adm:/var/adm:/sbin/nologin

lp:x:4:7:lp:/var/spool/lpd:/sbin/nologi006E  

sync:x:5:0:sync:/sbin:/bin/sync

 

命令说明:

-F 指定分隔符为冒号:

NR>=2 && NR<=6 这部分是条件,表示取第2行到第6行

注意:但是这里没有动作,这里大家需要了解如果只有条件(模式)没有动作,awk默认输出整行。

 

1.3.3 只有动作(干什么)

[root@admin /]# awk -F : '{print NR,$1}'/etc/passwd

1 root

2 bin

3 daemon

4 adm

5 lp

6 syn

….以下省略

 

命令说明:

-F 指定分隔符为冒号:

这里没有条件,表示对每一行都处理

{print NR,$1} 表示动作,显示NR行号与$1第一列内容

这里要理解没有条件的时候,awk会处理每一行

 

1.3.4 多个模式和动作

[root@admin /]# awk -F : 'NR==1{printNR,$1}NR==2{print NR,$NF}' /etc/passwd

1 root

2 /sbin/nologin

 

命令说明:

-F 指定分隔符为冒号:

这里有多个条件与动作的组合

NR==1 表示条件,行号NR 等于1条件满足的时候,执行{print NR,$1} 动作,输入行号与第一列

NR==2表示条件,行号(NR)等于2的条件满足的时候,执行{print NR,$NF}动作,输出行号与最后一列($NF)

1.4 注意:

  • pattern和{action} 需要用单引号引起来,防止shell作解释

awk -F : 'NR==1{print NR,$1}NR==2{print NR,$NF}'/etc/passwd

  • Pattern模式是可选的。如果不指定,awk将处理输入文件中的所有记录。如果指定一个模式,awk则只处理匹配指定的模式的记录。

  • {action}动作为awk命令,可以是单个命令,也可以是多个命令。整个action(包括里面的所有命令)都必须放在{和}之间。

  • action必须被{action} 包裹,没有被{action}包裹就是patern.

  • file要处理的目标文件。

  • 执行过程

  • 前,我们需要知道awk如何处理文件的。

在深入了解awk前,我们需要知道awk如何处理文件的。

实例1-2        示例文件的创建

[root@admin ~]# mkdir /server/files/ -p

[root@admin ~]# head /etc/passwd >/server/files/awkfile.txt

[root@admin ~]# cat /server/files/awkfile.txt

root:x:0:0:root:/root:/bin/bash

bin:x:1:1:bin:/bin:/sbin/nologin

daemon:x:2:2:daemon:/sbin:/sbin/nologin

adm:x:3:4:adm:/var/adm:/sbin/nologin

lp:x:4:7:lp:/var/spool/lpd:/sbin/nologin

sync:x:5:0:sync:/sbin:/bin/sync

shutdown:x:6:0:shutdown:/sbin:/sbin/shutdown

halt:x:7:0:halt:/sbin:/sbin/halt

mail:x:8:12:mail:/var/spool/mail:/sbin/nologin

uucp:x:10:14:uucp:/var/spool/uucp:/sbin/nologin

  这个文件仅包含十行文件,我们使用下面的命令:

实例1-3        示例1-6 awk执行过程演示

[root@admin ~]# awk 'NR>=2{print $0}'/server/files/awkfile.txt

bin:x:1:1:bin:/bin:/sbin/nologin

daemon:x:2:2:daemon:/sbin:/sbin/nologin

adm:x:3:4:adm:/var/adm:/sbin/nologin

lp:x:4:7:lp:/var/spool/lpd:/sbin/nologin

sync:x:5:0:sync:/sbin:/bin/sync

shutdown:x:6:0:shutdown:/sbin:/sbin/shutdown

halt:x:7:0:halt:/sbin:/sbin/halt

mail:x:8:12:mail:/var/spool/mail:/sbin/nologin

uucp:x:10:14:uucp:/var/spool/uucp:/sbin/nologin

 

命令说明:

条件NR>=2,表示行号大于等于2时候,执行{print $0}显示整行。

awk是通过一行一行的处理文件,这条命令中包含模式部分(条件)和动作部分(动作),awk将处理模式(条件)指定的行

1.7 awk指定流程图

 三剑客老大之awk命令上篇_第3张图片

1.8 小结awk执行过程

  1. awk读入第一行内容

  2. 判断是否符合模式中的条件NR>=2

  3. a)     如果匹配则执行相应的动作{print $0}

  4. b)如果不匹配条件,继续读取下一行

  5. 继续读取下一行

  6. 重复过程1-3,直到读取到最后一行(EFO;endof file 结束)

 

1.9 记录和字段

接下来我给大家来带两个新概念记录和字段,这里为了方便大家理解可以把记录就当做行及记录==行,字段相当于列。

名称

含义

record

记录,行

field

字段,列

 

1.10 记录(行)

awk对每个要处理的输入数据认为都是具有格式和结构的,而不仅仅是一堆字符串。默认情况下,每一行内容都是一条记录,并以换行符分隔(\n)结束。

实例1-4        查看一下下面这段文字

  1.思考:
一共有多少行呢?你如何知道的?通过什么标志?

root:x:0:0:root:/root:/bin/bash

bin:x:1:1:bin:/bin:/sbin/nologin

daemon:x:2:2:daemon:/sbin:/sbin/nologin

adm:x:3:4:adm:/var/adm:/sbin/nologin

lp:x:4:7:lp:/var/spool/lpd:/sbin/nologin

sync:x:5:0:sync:/sbin:/bin/sync

shutdown:x:6:0:shutdown:/sbin:/sbin/shutdown

halt:x:7:0:halt:/sbin:/sbin/halt

mail:x:8:12:mail:/var/spool/mail:/sbin/nologin

uucp:x:10:14:uucp:/var/spool/uucp:/sbin/nologin

 

1.11 ☆记录分隔符-RS

三剑客老大之awk命令上篇_第4张图片

 

  • awk默认情况下每一行都是一个记录(record)

  • RS及record separator 输入输出数据记录分隔符,每一行是怎么没得,表示每个记录输入的时候的分隔符,既行与行之间如果分隔. \n

  • NR既number of record 记录(行号),表示当前正在处理的记录(行)的号码

  • ORS既output record separator 输出记录分隔符

awk使用内置变量RS来存放输入记录分隔符,RS表示是输入记录分隔符,这个值可以通过BEGIN模块重新定义修改。

1.12 使用“/”为默认记录分隔符 修改RS变量(默认是\n回车)特殊条件BEGIN

实例1-5         

[root@admin files]# cat awkfile.txt

root:x:0:0:root:/root:/bin/bash

bin:x:1:1:bin:/bin:/sbin/nologin

daemon:x:2:2:daemon:/sbin:/sbin/nologin

adm:x:3:4:adm:/var/adm:/sbin/nologin

lp:x:4:7:lp:/var/spool/lpd:/sbin/nologin

sync:x:5:0:sync:/sbin:/bin/sync

shutdown:x:6:0:shutdown:/sbin:/sbin/shutdown

halt:x:7:0:halt:/sbin:/sbin/halt

mail:x:8:12:mail:/var/spool/mail:/sbin/nologin

uucp:x:10:14:uucp:/var/spool/uucp:/sbin/nologin

 

 

#与上面对比发现我们现在是以 /进行换行

[root@admin files]# awk 'BEGIN{RS="/"}{print NR,$0}'awkfile.txt

1 root:x:0:0:root:

2 root:

3 bin

4 bash

bin:x:1:1:bin:     

 

root:x:0:0:root:/root:/bin/bash 

bin:x:1:1:bin:/bin:/sbin/nologin

看到这个应该明白是怎么回事了吧对比

5 bin:

6 sbin

7 nologin

daemon:x:2:2:daemon:

8 sbin:

9 sbin

10 nologin

adm:x:3:4:adm:

11 var

12 adm:

13 sbin

14 nologin

lp:x:4:7:lp:

15 var

16 spool

17 lpd:

18 sbin

19 nologin

sync:x:5:0:sync:

20 sbin:

21 bin

22 sync

shutdown:x:6:0:shutdown:

23 sbin:

24 sbin

25 shutdown

halt:x:7:0:halt:

26 sbin:

27 sbin

28 halt

mail:x:8:12:mail:

29 var

30 spool

31 mail:

32 sbin

33 nologin

uucp:x:10:14:uucp:

34 var

35 spool

36 uucp:

37 sbin

38 nologin

 

命令说明

在每行开始先打印输出NR(记录号行号),并打印出每一行$0(整行)的内容

我们设置RS(记录分隔符)的值“/” 表示一行(记录)以“/” 结束

在awk眼中,文件是从头到尾一段连续的字符串,恰巧中间有些\n(回车换行符),\n也是字符

 

1.13 ☆回顾记录(行)到底是什么意思?

  • 记录(行):默认以\n(回车换行)结束。而这个行的结束不就是记录分割符RS。

  • 所以在awk中,RS(记录分隔符)变量表示这行的结束符号(默认是回车换行)

  • 在工作中,我们可以通过修改RS变量的值来决定行的结束标志,最终来决定“每行”的内容

注意:

awk 的BEGIN模块,在后面详解,此处大家知道BEGIN模块里面定义一些awk内置变量即可。

1.14 对$0的认识

  $0表示整行,其实awk使用$0表示整条记录。记录分隔符存在RS变量中,或者说每个记录以RS内置变量结束。

  另外,awk每一行的记录都有一个内置变量NR来保存,没处理完一条记录,NR的值就会自动+1

  下面通过实例加深印象

[root@admin files]# awk '{print NR,$0}'awkfile.txt

1 root:x:0:0:root:/root:/bin/bash

2 bin:x:1:1:bin:/bin:/sbin/nologin

3 daemon:x:2:2:daemon:/sbin:/sbin/nologin

4 adm:x:3:4:adm:/var/adm:/sbin/nologin

5 lp:x:4:7:lp:/var/spool/lpd:/sbin/nologin

6 sync:x:5:0:sync:/sbin:/bin/sync

7 shutdown:x:6:0:shutdown:/sbin:/sbin/shutdown

8 halt:x:7:0:halt:/sbin:/sbin/halt

9 mail:x:8:12:mail:/var/spool/mail:/sbin/nologin

10 uucp:x:10:14:uucp:/var/spool/uucp:/sbin/nologin

 

命令说明:

NR及number of record ,当前记录的记录号,刚开始学也可以理解为行号。

$0表示整行或者说整个记录

1.15 企业面试题一:

1.15.1 企业面试题:按单词出现频率降序排序(计算文件中每个单词的重复数量)

注:(此处使用sort与uniq即可)  

命令: sort 排序   uniq 配合sort 将重复的单词等数字的合并

题目:

题目创建方法:
sed -r '1,10s#[^a-zA-Z]+# #g' /etc/passwd>/server/files/count.txt

 

[root@admin files]# cat count.txt

root x root root bin bash

bin x bin bin sbin nologin

daemon x daemon sbin sbin nologin

adm x adm var adm sbin nologin

lp x lp var spool lpd sbin nologin

sync x sync sbin bin sync

shutdown x shutdown sbin sbin shutdown

halt x halt sbin sbin halt

mail x mail var spool mail sbin nologin

uucp x uucp var spool uucp sbin nologin

~                                       

思路:

让所有单词排成一列,这样每个单词都是单独的一行

  • 设置RS值为空格
    2)将文件里面的所有空格替换为回车换行符“\n”
    3)grep所有连续的字母,grep-o参数让他们排成一列。

方法:将所有字母排成一列

方法一:xargs 分组 将所有字母

[root@admin files]# xargs -n 1 < count.txt

 

方法二:修改默认的RS记录分隔符 \n  换成空格  这样就会显示一列

[root@admin files]# awk 'BEGIN{RS=""}{print $0}' count.txt

 

方法三:tr虽然是sed的阉割版但是其功能还是挺强大的 所有的空格替换成\n换行符 这样就达到我们想要的效果了  sed是一行一行读入  放在模式空间换不了\n   

[root@admin files]# cat count.txt | tr "" "\n"

 

方法四: egrep将所有字母过滤出来

-o 精确匹配

利用正则表达式 小写a到大写Z

+ 连续重复前面一个字符或多个字符

# cat count.txt | egrep -o "[a-Z]+"

 

 

1.15.2 实战解题

1.15.2.1         方法一:

[root@admin files]# xargs -n 1 < count.txt |sort | uniq -c

      3 adm

      1 bash

      5 bin

      2daemon

      3 halt

      2 lp

      1 lpd

      3 mail

      6nologin

      3 root

     12 sbin

      3shutdown

      3spool

      3 sync

      3 uucp

      4 var

     10 x

 

 

1.15.2.2         方法二:

[root@admin files]# awk 'BEGIN{RS=""}{print $0}' count.txt | sort | uniq -c

      1

      3 adm

      1 bash

      5 bin

      2daemon

      3 halt

      2 lp

      1 lpd

      3 mail

      6nologin

      3 root

     12 sbin

      3shutdown

      3spool

      3 sync

      3 uucp

      4 var

     10 x

1.15.2.3         方法三:

[root@admin files]# cat count.txt  | tr " " "\n" | sort  | uniq -c

      3 adm

      1 bash

      5 bin

      2daemon

      3 halt

      2 lp

      1 lpd

      3 mail

      6nologin

      3 root

     12 sbin

      3shutdown

      3spool

      3 sync

      3 uucp

      4 var

     10 x

 

 

1.15.2.4         方法四:

[root@admin files]# cat count.txt | egrep -o"[a-Z]+" | sort | uniq -c

      3 adm

      1 bash

      5 bin

      2daemon

      3 halt

      2 lp

      1 lpd

      3 mail

      6nologin

      3 root

     12 sbin

      3shutdown

      3spool

      3 sync

      3 uucp

      4 var

     10 x

 

1.16   awk记录知识小结

  • NR存放着每个记录的号(行号)读取新行的时候会自动+1

  • RS是输入数据的记录的分隔符,简单理解就是制定每个记录的行的结尾标志\n.

  • RS作用就是表示一个记录的结束

  • ORS输出数据的记录的分隔符

  • 学习技巧一则:

大象放冰箱分几步?打开冰箱,把大象放进去,关闭冰箱门。
awk也是一样的,一步一步来,先修改了RS,然后用NR调试,看看到底如何分隔的。然后通过sort排序,uniq -c去重

1.18 ☆字段(列)

  • 每条记录都是有多个区域(field)组成的,默认情况下区域之间的分隔符是由(及空格或制表符)来分隔,并且将分隔记录在内置变量FS中,每行记录的区域数

  • 三剑客老大之awk命令上篇_第5张图片


FS既fieldseparator,输入字段(列)分隔符。分隔符就是菜刀,把一行字符串切为很多个区域。

NF既number offileds,表示一行中(字段)的个数,可以理解为菜刀且过一行后,切成了多少份。

1.19 OFS输出字段(列)分隔符

  • awk使用内置变量FS来记录区域分隔符的内容,FS可以在命令行上通过-F 参数来更改,也可以通过BEGIN模块来更改。'BEGIN{FS=":"}{printNR,$1}'

 

  • 然后通过$n,n是整数,来取被切割后的区域,$1取第一个区域,    $2取第二个区域,$NF取最后一个区域。

  • 下面通过实例来加强学习:

实例1-6        指定分割符:

[root@admin files]# awk -F " " '{print$1}' count.txt

root

bin

daemon

adm

 

命令说明:

以:(冒号) 为分隔符,打印第一列内容

  • 此处的FS是一个字符,其实他可以指定多个字符,此时FS指定的值可以是一个正则表达式。

  • 正常情况下,当你指定分隔符(非空格)的时候,例如指定多个区域分隔符,每个分隔符就是一把刀,把左右两边切为两个部分。

实例1-7        同时取出zhaokai和10206334这两个内容。

[root@admin files]# cat qq.txt

I am zhaokai,my qq is 10206334

思路:

我们用默认的想法一次使用一把刀,需要配合管道的。如果同时使用两把刀呢?看下面的结果

[root@admin files]# awk -F "[ ,]"'{print $3,$NF}' qq.txt

zhaokai 10206334

 

命令说明:

通过命令-F 参数指定区域分隔符

[, ] 是正则表达式里面的内容,它表示一个整体,一个空格和一个逗号,合并在一起,就表示以空格或者逗号为区域分隔符。

 

小技巧:

  在动作(‘{print \$3,\$NF}’)里面的逗号,表示空格,其实动作中的逗号就是OFS的值,我们会在后面说明。刚开始大家把动作中的都逗号,当作空格即可。

1.21 默认分隔符和指定分隔符会有些差异

 

例:默认分隔符和指定分隔符会有些差异

[root@admin files]# ifconfig eth0 | awk 'NR==2'>/server/files/awkblank.txt

[root@admin files]# cat /server/files/awkblank.txt

         inet addr:192.168.197.133 Bcast:192.168.197.255 Mask:255.255.255.0

#默认分隔符时候

[root@admin files]# awk '{print $1}'/server/files/awkblank.txt

inet

#指定分隔符时候

[root@admin files]# awk -F "[ :]+"'{print $1}' /server/files/awkblank.txt

 

[root@admin files]# awk -F "[ :]+"'{print $2}' /server/files/awkblank.txt

inet

 

命令说明:

awk默认的FS分隔符对于空格序列,一个空格或多个空格tab都认为是一样的,一个整体。

  • 这个文件的开头有很多连续的空格,然后才是inet这个字符

  • 当我们使用默认的分隔符的时候,$1是有内容的。

  • 当我们指定其他分隔符(非空格)时候,区域会有所变化

  • 到底为何会这样,我们在这里不再深入研究,只要了解有这种情况,注意一下即可。

 

1.22 ORS与OFS简介修改FS、RS

现在说说ORS和OFS这两个内置变量的含义。

  RS是输入记录分隔符,决定awk如何读取或分隔每行(记录)

  ORS表示输出记录分隔符,决定awk如何输出一行(记录)的,默认是回车换行(\n)

  FS是输入区域分隔符,决定awk读入一行后如何再分为多个区域。

  OFS表示输出区域分隔符,决定awk输出每个区域的时候使用什么分隔她们。

  awk无比强大,你可以通过RS,FS决定awk如何读取数据。你也可以通过修改ORS,OFS的值指定awk如何输出数据。

修改FS

[root@admin /]# awk 'BEGIN{FS=":"}{print$1}' /etc/passwd

 

修改RS   记得查看是用NR显示行号比较方便

[root@admin /]# awk 'BEGIN{RS=":"}{print$0}' /etc/passwd

 

三剑客老大之awk命令上篇_第6张图片

1.23 字段与记录小结()

  现在你应该会对awk的记录字段有所了解了,下面我们总结一下,学会给阶段性知识总结是学好运维的必备技能。

三剑客老大之awk命令上篇_第7张图片

RS记录分隔符,表示每行的结束标志,默认是\n

NR行号(记录号)

FS字段分隔符,每列的分隔标志或结束标志

NF就是每行有多少列,每个记录中字段的数量

$符号就是取某个列(字段),$1$2$NF

FS ( awk -F )分隔符,-F “:”《==》‘BEGIN{FS=":"}’

RS记录分隔符(行的结束标示)

选择合适的刀FS,RS,OFS,ORS

分隔符è结束标示

记录与区域字段,你就对我们所谓的行与列,有了新的认识。

1.24 awk基础入门总结

  • awk命令行结构

  • awk的模式和动作

  • awk的记录和字段

  • 比较核心常用的是字段

  • 另外这些企业面试题可是学会awk的必备,必须自己能写出来。

第2章 awk进阶

2.1 awk模式与动作

接下来就详细介绍下,awk的模式都有几种

  • 正则表达式作为模式

  • 比较表达式作为模式

  • 范围模式

  • 特殊模式BEGIN和END

awk的模式是你玩好awk必备也是最基础的内容,必须熟练掌握

2.2 正则表达式作为模式

  awk同sed一样也可以通过模式匹配来对输入的文本进行匹配。说到模式匹配,肯定少不了正则表达式模式,大部分与sed支持的元字符类似,而且正则表达式是玩转三剑客必备工具,下表列出awk支持的正则表达式元字符:

 

awk模式就支持正则表达式符号

元字符

功能

示例

解释

^

字符串开头

/^admin/或\$3~/^admin/

匹配所有以admin开头的字符串;匹配出所有第三列中以admin开头的

\$

字符串结尾

/admin$/或$3~/admin$/

匹配所有以admin结尾的字符串;匹配第三列中以admin结尾的

.(点)

匹配任意但个字符(包括回车符)

/c..l/

匹配字母c,然后两个任意字符,再以l结尾的行

*

重复0个或多个前一个字符

/a*cool/

匹配0个或多个a之后紧跟着cool的行

+

重复前一个字符一次或多次

/a+b/

匹配一个或多个a加上字符串b的行

?

匹配0个或一个前边的字符

/a?b/

匹配以字母a或b或c开头的行

[]

匹配指定字符组内的任一个字符

/^[abc]/

匹配以字母a或b或c开头的行

[^]

匹配不在指定字符组内的任一字符

/^[^abc]/

匹配不以字母a或b或c开头的行

()

子表达式组合

/(admin)+/

表示一个或多个cool组合,当有一些字符需要组合时,使用括号括起来

|

或者的意思

/(admin)|B/

匹配admin或字母B的行

 

 

2.3 ☆awk正则匹配操作符

 

awk正则匹配的操作符

~

 

 

用于对记录或区域的(行列)表达式进行匹配

awk '$1/zhaokai/{print $1}' test.txt

 

用于表达式与~相反的意思

 

 

实战例子:

root@admin files]# cat zhaokai.txt | awk'$1~/zhaokai/'

zhaokai like linux

[root@admin files]# cat zhaokai.txt | awk'$1~/zhaokai/{print $1}'

zhaokai

 

2.4 下面通过具体例子看看,awk如果通过正则表达式字符串的

2.4.1 awk正则表达式匹配整行

[root@admin files]# awk '/^root/{print $1}'awkfile.txt

root:x:0:0:root:/root:/bin/bash

 

和上面效果一样

[root@admin files]# awk -F ":"'$0~/^root/' awkfile.txt

root:x:0:0:root:/root:/bin/bash

awk只用正则表达式的时候是默认匹配整行的即‘$0~/^root/’和‘/^root/’是一样的。

 

打印最后一列 -F 指定分隔符 :

[root@admin files]# awk -F ":"'/^root/{print $NF}' awkfile.txt

/bin/bash

 

2.4.2 awk正则表达式匹配一行中的某一列

[root@admin files]# awk -F ":"'$5~/shutdown/' awkfile.txt

shutdown:x:6:0:shutdown:/sbin:/sbin/shutdown

 

  • 提示:

  • $5表示第五个区域(列)

  • ~表示匹配(正则表达式匹配)

  • /shutdown/表示匹配shutdown这个字符串

  • 合并在一起

  • $5~/shutdown/表示第五个区域(列)匹配正则表达式/shutdown/,既第5列包含shutdown这个字符串,则显示这一行。

 

 

2.5某个区域中的开头和结尾

  • ^匹配一个字符串的开头|
    $匹配一个字符串的结尾|

  • 在sed和grep这两个命令中,我们都把它们当作行的开头和结尾。但是在awk中它表示的是字符串的开头和结尾

 

2.6接下来我们通过练习题来联系awk如何使用正则表达式。

2.6.1 创建测试环境

[root@admin files]# vim reg.txt

Zhang Dandan   41117397   :250:100:175

Zhang Xiaoyu   390320151  :155:90:201

Meng Feixue    80042789   :250:60:50

Wu   Waiwai    70271111  :250:80:75

Liu  Bingbing  41117483   :250:100:175

Wang Xiaoai    3515064655 :50:95:135

Zi   Gege      1986787350 :250:168:200

Li   Youjiu    918391635  :175:75:300

Lao  Nanhai    918391635  :250:100:175

~                                            

 

2.6.2测试文件说明

  • 第一列是姓氏

  • 第二列是名字

  • 第一列第二列合起来就是姓名

  • 第三列是对应的ID号码

  • 最后三列是三次捐款数量

  • awk正则表达式练习题

  • 练习题1:显示姓Zhang的人的第二次捐款金额及她的名字

  • 练习题2:显示Xiaoyu的名字和ID号码

  • 练习题3:显示所有以41开头的ID号码的人的全名和ID号码

  • 练习题4:显示所有以一个D或X开头的人名全名

  • 练习题5:显示所有ID号码最后一位数字是1或5的人的全名

  • 练习题6:显示Xiaoyu的捐款,每个值都有以$开头。如$520$200$135

  • 练习题7:显示所有人的全名,以姓,名的格式显示,如Meng,Feixue

  • 1显示姓Zhang的人的第二次捐款金额及她的名字

方法一:必须掌握

[root@admin files]# awk -F "[ :]+"'$1~/^Zhang/{print $1,$5}' reg.txt

Zhang 100

Zhang 90

 

方法二:

[root@admin files]awk -F "[ :]+"'$1~/^Zhang/{print $2,$(NF-1)}' reg.txt

 

 

/Zhang/ 条件  这一行中如果有Zhang满足条件 

第一列 或者以Zhang 开头并结尾

说明:

-F 指定分隔符,现在知道-F 及FS也是支持正则表达式的。

[: ]+  表示连续空格或冒号  +重复一个或一个以上前面的字符。

/Zhang/ 表示条件,整行中包含Dan字符的这个条件

{print $1,$5}表示动作,满足条件后,执行显示第一列和第五列

注意:
NF是一行中有多少列,NF-1整行就是倒数第二列。
$(NF-1)就是取倒数第二列内容。

2.6.52显示Xiaoyu的名字和ID号码

方法一:必须掌握

[root@admin files]# awk '$2~/Xiaoyu/{print $1,$3}'reg.txt

Zhang 390320151

 

方法二:

[root@admin files]# awk -F "[ :]+"'$2~/^Xiaoyu/{print $1,$3}' reg.txt

命令说明:

指定分隔符-F “【:】+”

$2~/Xiaoyu/表示条件,第二列包含Xiaoyu时候执行对应的动作

{print $1,$3}表示动作,显示第一列和第三列的内容

 

思路:

[root@oldboyedu-35 files]# ###第一个里程碑-确定好目标并选好武器 
[root@oldboyedu-35 files]# ###第二里程碑-- 确定好条件    找谁
[root@oldboyedu-35 files]# awk '$2~/Xiaoyu/' reg.txt 
Zhang Xiaoyu    390320151  :155:90:201
[root@oldboyedu-35 files]# 
[root@oldboyedu-35 files]# ###第三个里程碑-只显示你想要的内容

 

2.6.63显示所有以41开头的ID号码的人的全名和ID号码

方法以:

[root@admin files]# awk '$3~/^41/{print $1,$2,$3}'reg.txt

Zhang Dandan 41117397

Liu Bingbing 41117483

 

第一步:确定好目标

第二步:确定好条件 找谁

第三步:显示你想要的内容

2.6.74显示所有以一个D或X开头的人名全名

方法一:

[root@admin files]# awk '$2~/^[DX]/{print $1,$2}'reg.txt

Zhang Dandan

Zhang Xiaoyu

Wang Xiaoai

 

方法二:

[root@admin files]awk -F "[ :]+"'$2~/^D|^X/{print $1,$2}' reg.txt

Zhang Dandan

Zhang Xiaoyu

Wang Xiaoai

 

命令说明:

^以什么开头

|  或

注意:
这里要用[ ]括号表示即^[DX]相当于^D|^X,有的同学写成^D|X这样是错误的。

2.6.85显示所有ID号码最后一位数字是1或5的人的全名

#和第三题类型

方法一:

[root@admin files]# awk '$3~/[15]$/{print $1,$2}'reg.txt

Zhang Xiaoyu

Wu Waiwai

Wang Xiaoai

Li Youjiu

Lao Nanhai

 

方法二:

[root@admin files]awk -F "[ :]+"'$3~/1$|5$/{print $1,$2}' reg.txt

Zhang Xiaoyu

Wu Waiwai

Wang Xiaoai

Li Youjiu

Lao Nanhai

 

 

2.6.96: 显示Xiaoyu的捐款,每个值都有以$开头。如$520$200$135

方法一:

awk -F "[ :]+" '$2~/Xiaoyu/{print"$"$4"$"$5"$"$6}' reg.txt

 

方法二:awk替换强大功能

[root@admin files]# awk'/Xiaoyu/{gsub(/:/,"$");print $4}' reg.txt

$155$90$201

 

[root@oldboyedu-35 files]# ###awk内置的功能(函数)
[root@oldboyedu-35 files]# ####查找 替换    gsub 
[root@oldboyedu-35 files]# ####gsub(/找谁/,"替换成什么")
[root@oldboyedu-35 files]# ####gsub(/找谁/,"替换成什么",替换那个部分)

 

2.6.107:显示所有人的全名,以姓,名的格式显示,如Meng,Feixue

方法一:

[root@admin files]# awk '{print $1,$2}' reg.txt

Zhang Dandan

Zhang Xiaoyu

Meng Feixue

Wu Waiwai

Liu Bingbing

Wang Xiaoai

Zi Gege

Li Youjiu

Lao Nanhai

 

方法二:

[root@admin files]awk -F "[ ]+" '{print$1","$2}' reg.txt


awk功能很强大,玩会了很牛逼。