文本处理三剑客

1. 文本处理三剑客

命令

描述

grep

默认不支持扩展表达式,加-E 选项开启 ERE。如果不加-E 使用花括号要加转义符\{\}

egrep

支持基础和扩展表达式

awk

支持 egrep 所有的正则表达式

sed

默认不支持扩展表达式,加-r 选项开启 ERE。如果不加-r 使用花括号要加转义符\{\}

 

2. sed详解

2.1  概述

  我们都知道,在Linux中一切皆文件,比如配置文件,日志文件,启动文件等等。如果我们相对这些文件进行一些编辑查询等操作时,我们可能会想到一些vi,vim,cat,more等命令。但是这些命令效率不高,而在linux中有三种工具:顶配awk,中配sed,标配grep。使用这些工具,我们能够在达到同样效果的前提下节省大量的重复性工作,提高效率。

  文件内容可以是来自文件,也可以直接来自键盘或者管道等标准输入,最后的结果默认情况下是显示到终端的屏幕上,但是也可以输出到文件中。

  编辑文件也是这样,以前我们修改一个配置文件,需要移动光标到某一行,然后添加点文字,然后又移动光标到另一行,注释点东西.......可能修改一个配置文件下来需要花费数十分钟,还有可能改错了配置文件,又得返工。这还是一个配置文件,如果数十个数百个呢?因此当你学会了sed命令,你会发现利用它处理文件中的一系列修改是很有用的。只要想到在大约100多个文件中,处理20个不同的编辑操作可以在几分钟之内完成,你就会知道sed的强大了。

  sed操作之前一定要备份文件;

  sed操作推荐使用单引号,awk亦是如此。

2.2 语法格式

  sed  [选项]  [sed命令]  [输入文件]

  说明: 

  注意sed软件以及后面选项,sed命令和输入文件,每个元素之间都至少有一个空格。 

  sed -commands(sed命令)是sed软件内置的一些命令选项,为了和前面的options(选项)区分,故称为sed命令 

  sed -commands 既可以是单个sed命令,也可以是多个sed命令组合。

  input -file (输入文件)是可选项,sed还能够从标准输入如管道获取输入。

2.3 sed的工作原理

  sed读取一行,首先将这行放入到缓存中,然后,才对这行进行处理,处理完成以后,将缓冲区的内容发送到终端。存储sed读取到的内容的缓存区空间称之为:模式空间(Pattern Space)

2.4 选项

选项

说明

-n(no)

取消默认的sed软件的输出,常与sed命令的p连用。

-e(entry)

一行命令语句可以执行多条sed命令

-r(ruguler)

使用扩展正则表达式,默认情况sed只识别基本正则表达式

-i(inside)

直接修改文件内容,而不是输出到终端,如果不使用-i选项sed软件只是修改在内存中的数据,并不会影响磁盘上的文件*

2.5 sed命令

sed-command

说明

a (append)

追加,在指定行后添加一行或多行文本

c (change)

取代指定的行

d (delete)

删除指定的行

i (insert)

插入,在指定行前添加一行或多行文本

p (print)

打印模式空间内容,通常p会与选项-n一起使用

特殊符号

说明

对指定行以外的所有行应用命令(取反)

2.5 sed增删改查

1) 增

  2个sed命令,分别是:

  “a”: apend,追加,追加文本到指定行后。

  “I”: insert,插入,插入文本到指定行前。

#在第一行后面追加3行,不加-i不改变源文件
[root@localhost ~]# sed "1a 1\n2\n3\n" test
root:x:0:0:root:/root:/bin/bash
1
2
3
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

#在行首添加一行
[root@localhost ~]# sed "1i 1234" test
1234
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

 

2)删

  这个功能也是非常得有用,比如我们想删除文件中的某些行,以前最常用的是vi或vim命令,但现在我们知道了sed命令,就应该使用这个高逼格的命令完成任务了。

  “d”:delete,删除,删除文本。

  sed软件可以对单行或多行文本进行处理。如果在sed命令前面不指定地址范围,那么默认会匹配所有行。

  sed中使用单引号。

#从第1行起删除1行
[root@localhost ~]# sed "1d" test
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

#删除1-3行
[root@localhost ~]# sed "1,3d" test
adm:x:3:4:adm:/var/adm:/sbin/nologin
lp:x:4:7:lp:/var/spool/lpd:/sbin/nologin

#删除全文
[root@localhost ~]# sed "d" test
[root@localhost ~]# 

#删除匹配到root的行
[root@localhost ~]# sed "/root/d" test        #/ /表示匹配范围,而且支持正则
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
 
#支持正则:删除以bin开头的行
[root@localhost ~]# sed "/^bin/d" test
root:x:0:0:root:/root:/bin/bash
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

#删除第3行到末尾行
[root@localhost ~]# sed '3,$d' test           #注意是单引号
root:x:0:0:root:/root:/bin/bash 
bin:x:1:1:bin:/bin:/sbin/nologin


#删除1-3行以外的行(取反)
[root@localhost ~]# sed '1,3!d' test
root:x:0:0:root:/root:/bin/bash
bin:x:1:1:bin:/bin:/sbin/nologin
daemon:x:2:2:daemon:/sbin:/sbin/nologin

 3)改

  “c”:用新行取代旧行,记忆方法:c的全拼是change,意思是替换。

#将第一行替换为 this is zxj
[root@localhost ~]# sed '1c this is zxj' test
this is zxj
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

4)文本替换

  使用sed软件80%的场景是使用替换功能

  选项:

    “s”:单独使用-->将每一行中第一处匹配的字符串进行替换==>sed命令
    “g”:每一行进行全部替换-->sed命令s的替换标志之一(全局替换),非sed命令。
    “-i”:修改文件内容-->sed软件的选项,注意和sed命令i区别。

  替换模型:

    sed -i 's/目标内容/替换内容/g'  ken.log
    sed -i 's#目标内容#替换内容#g'

#将root替换为zxj
[root@localhost ~]# sed 's/root/zxj/' test
zxj: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
 
#将所有的root替换为zxj
[root@localhost ~]# sed 's/root/zxj/g' test
zxj:x:0:0:zxj:/zxj:/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


#确认无误将源文件替换(-i)
[root@localhost ~]# sed  -i 's/root/zxj/g' test
[root@localhost ~]# cat test
zxj:x:0:0:zxj:/zxj:/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

#匹配以zxj开头的行,将该行所有的zxj替换为root
[root@localhost ~]# sed -i '/^zxj/{s/zxj/root/g}' test
[root@localhost ~]# cat test
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

5)查

  这个功能也是非常得有用,比如我们想查看文件中的某些行,以前最常用的是cat或more或less命令等,但这些命令有些缺点,就是不能查看指定的行。而我们用了很久的sed命令就有了这个功能了。而且我们前面也说过使用sed比其他命令vim等读取速度更快!

这里我们需要用到1个sed命令

  “p”: print,打印,输出指定内容,但默认会输出2次匹配的结果,因此使用-n选项取消默认输出。

#显示第2行(包括模式空间文件)
[root@localhost ~]# sed '2p' test
root:x:0:0:root:/root:/bin/bash
bin:x:1:1:bin:/bin:/sbin/nologin
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 

#-n与p连用,不显示缓存文件,只显示第2行
[root@localhost ~]# sed -n '2p' test
bin:x:1:1:bin:/bin:/sbin/nologin
[root@localhost ~]#

6> sed用法总结 

1)查找指定的字符串

  例子:显示/etc/passwd中包含root的行(显示模式空间中的内容)

  方法1:set '/root/p' /etc/passwd

  方法2:cat /etc/passwd | sed '/root/p'

2)在指定的位置做增删

  例子:删除以root为开头的行

  # sed '/^root/d' a.txt

  例子:在包含root的行后添加一行 i am ken

  # sed '/root/a i am ken' a.txt

3)按行替换

  例子:将5到9行的内容替换为 i am ken

  # sed '5,9c i am ken' a.txt

 4)按照字符替换

  例子:将/etc/selinux/config中的SELINUX=enforcing改成 disabled

  写法1:# sed -i 's/SELINUX=disabled/SELINUX=enforcing/g' config

  写法2:# sed -r -i 's/(SELINUX=)disabled/\1enforcing/g' config

5)查找指定的内容再做替换

  例子:将以r开头的行中的oo替换为qq

  # sed '/^r/{s/oo/qq/g}' passwd

 6)多点编辑

  例子:去除文件中的注释行和空白行

  # grep -v -E "(^#)|(^$)" passwd.bak >passwd

  # cat passwd.bak | sed -e '/^#/d' -e '/^$/d' >passwd

#源文件
[root@localhost ~]# cat test
#root:x:0:0:root:/root:/bin/bash
#root:x:0:0:root:/root:/bin/bash
root:x:0:0:root:/root:/bin/bash
#bin:x:1:1:bin:/bin:/sbin/nologin
daemon:x:2:2:daemon:/sbin:/sbin/nologin
#bin:x:1:1:bin:/bin:/sbin/nologin
adm:x:3:4:adm:/var/adm:/sbin/nologin

 

#bin:x:1:1:bin:/bin:/sbin/nologin
lp:x:4:7:lp:/var/spool/lpd:/sbin/nologin


#删除以#开头的行和空行。有几条命令写几个
-e [root@localhost ~]# sed -i -e '/^#/d' -e '/^$/d' test [root@localhost ~]# cat test root:x:0:0:root:/root:/bin/bash 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

 7)取反操作

  显示非1-3行

  # sed -n '1,3!p' passwd

3. awk详解

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

3.1  awk格式

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

  模式既pattern,可以类似理解成sed的模式匹配,可以由表达式组成,也可以是两个正斜杠之间的正则表达式。比如NR==1,这就是模式,可以把他理解为一个条件。

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

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

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

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

3.2  awk参数

  -F:指定分隔符

3.3  部分概念

  记录(record):一行就是一个记录

  分隔符(field separator):进行对记录进行切割的时候所使用的字符

  字段(field):将一条记录分割成的每一段

  FILENAME:当前处理文件的文件名

  FS(Field Separator):字段分隔符(默认是以空格为分隔符)

  NR(Number of Rrecord):行号,记录的编号(awk每读取一行,NR就加1)

  NF(Number of Field):字段数量(记录了当前这条记录包含多少个字段)

  ORS(Output Record Separator):指定输出记录分隔符(指定在输出结果中记录末尾是什么,默认是\n,也就是换行)

  OFS(Output Field Separator):输出字段分隔符

  RS:记录分隔符

 

3.4  输出字段的表达方式

  $1 $2 ... $n 输出一个指定的字段

  $NF 输出最后一个字段

  $0 输出整条记录

 

3.5  awk的执行过程

#打印出整条记录的行号,{};里面是执行的命令
[root@localhost ~]# sed -i '1i this is zxj' test           #添加一行
[root@localhost ~]# cat test
this is zxj
root:x:0:0:root:/root:/bin/bash
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
[root@localhost ~]# cat test | awk '{print NR,$o}'         #打印行号,指定整段
1 this is zxj
2 root:x:0:0:root:/root:/bin/bash
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
[root@localhost ~]# cat test | awk '{print NR}'            #没有$0,只打印行号
1
2
3
4
5
 
#只打印第二行
[root@localhost ~]# cat test | awk 'NR==2{print $0}'
                 #找谁,要干什么;找到第2行,找到后将第2行整段打印出来。注意是==而不是=
root:x:0:0:root:/root:/bin/bash 

#打印2到4行
[root@localhost ~]# cat test | awk 'NR>=2&&NR<=4{print $0}'    #与
root:x:0:0:root:/root:/bin/bash
daemon:x:2:2:daemon:/sbin:/sbin/nologin
adm:x:3:4:adm:/var/adm:/sbin/nologin
 
#只打印2和4行
[root@localhost ~]# cat test | awk 'NR==2||NR==4{print $0}'
root:x:0:0:root:/root:/bin/bash
adm:x:3:4:adm:/var/adm:/sbin/nologin
[root@localhost ~]# cat test | awk 'NR==2||NR==4{print NR,$0}'  #带行号
2 root:x:0:0:root:/root:/bin/bash
4 adm:x:3:4:adm:/var/adm:/sbin/nologin
[root@localhost~]# awk 'NR>=2&&NR<=5{print $0}' /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/nologin


  命令说明: 条件NR>=2,表示行号大于等于2时候,执行{print $0}显示整行。 awk是通过一行一行的处理文件,这条命令中包含模式部分(条件)和动作部分(动作),awk将处理模式(条件)指定的行。

  1)awk读入第一行内容

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

  a,如果匹配则执行对应的动作{print $0}
  b,如果不匹配条件,继续读取下一行

  3)继续读取下一行                                  
  4)重复过程1-3,直到读取到最后一行(EOF:end of file)

 

3.5 awk进阶—正则

  正则表达式的运用,默认是在行内查找匹配的字符串,若有匹配则执行action操作,但是有时候仅需要固定的列来匹配指定的正则表达式,比如:我想取/etc/passwd文件中第五列{$5}这一列查找匹配mail字符串的行,这样就需要用另外两个匹配操作符,并且awk里面只有这两个操作符来匹配正则表达式。

  

#awk支持正则匹配
[root@localhost ~]# awk '/^root/' test                    #匹配root开头的行
root:x:0:0:root:/root:/bin/bash
[root@localhost ~]# awk '/^root/{print NR,$0}' test       #打印出以root开头的行
2 root:x:0:0:root:/root:/bin/bash
[root@localhost ~]# awk '$0~/^root/{print NR,$0}' test    #~表示要申明使用正则,在$0整行里匹配以root开头的行,若匹配到则将其打印出来
2 root:x:0:0:root:/root:/bin/bash
 
#只打印以/分割的第四字段(最后一个字段)
[root@localhost ~]# awk -F "/" '{print $4}' test
bash
nologin
nologin
sbin
lpd:
sync
shutdown
halt
mail:
nologin

#取出以bash结尾的行中的bash
[root@localhost ~]# head /etc/passwd > test               #准备文件
[root@localhost ~]# cat test
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
operator:x:11:0:operator:/root:/sbin/nologin
[root@localhost ~]# awk -F "/" '/bash$/{print $NF}' test  #找到bash,以bash结尾$NF表示最后一个字段
bash
[root@localhost ~]# awk -F "/" '/bash$/{print $4}' test   #同理,以/分割的第4个字段(最后一个字段),为bash的行,打印出
bash
 
#指定打印第7行第四列
[root@localhost ~]# awk -F ":" 'NR==2{print $NR}' test
x
 
#打印出/etc/passwd中的用户和用户类型(第一列和最后一列)
[root@localhost ~]# awk -F ":" '{print $1,$NF}' /etc/passwd
root /bin/bash
bin /sbin/nologin
daemon /sbin/nologin
…………

#取出网卡ip
#方法一:
[root@localhost ~]# ip a | grep 'global'                  #取出该行
    inet 192.168.16.5/24 brd 192.168.16.255 scope global ens33
[root@localhost ~]# ip a | grep 'global' | awk -F " " '{print $2}'
192.168.16.5/24                                           #空格分割取出ip段
[root@localhost ~]# ip a | grep 'global' | awk -F " " '{print $2}' |  awk -F "/" '{print $1}'         # /分割取出ip
192.168.16.5

#方法二:
[root@localhost ~]# ip a | grep "global" | awk -F "( +)|(/)" '{print $3}'   #分组,以空格和/分割的第三部分
192.168.16.5

3.6 awk特殊模式—BEGIN模式和END模式

  BEGIN模块在awk读取文件之前就执行,一般用来定义我们的内置变量(预定义变量,eg:FS,RS)

  需要注意的是BEGIN模式后面要接跟一个action操作块,包含在大括号内。awk必须在输入文件进行任何处理前先执行BEGIN里的动作(action)。可以不要任何输入文件,就可以对BEGIN模块进行测试,因为awk需要先执行完BEGIN模式,才对输入文件做处理。BEGIN模式常常被用来修改内置变量ORS,RS,FS,OFS等值。

1)BEGIN模式

[root@localhost ~]# cat test | awk -F ":" 'BEGIN{print"userinfor,shelltype"}{print $1,$NF}'
userinfor,shelltype                   #先执行BEGIN模块,再执行awk读取文件
root /bin/bash
bin /sbin/nologin
daemon /sbin/nologin
adm /sbin/nologin
lp /sbin/nologin
sync /bin/sync
shutdown /sbin/shutdown
halt /sbin/halt
mail /sbin/nologin
operator /sbin/nologin

#用awk取ip第三种方法:
[root@localhost ~]# ip a | grep "global" | awk 'BEGIN{FS="( +)|(/)"}{print $3}'        #awk先执行BEGIN模块,FS表示字段分割符,以空格和/进行分割的第三部分,省去选项-F
192.168.16.5

2)END模式

  END在awk读取完所有的文件的时候,再执行END模块,一般用来输出一个结果(累加,数组结果),也可以是和BEGIN模块类似的结尾标识信息

  与BEGIN模式相对应的END模式,格式一样,但是END模式仅在awk处理完所有输入行后才进行处理。

#END作用与BEGIN相反
[root@localhost ~]# cat test | awk -F ":" '{print $1,$7}END{print "end of file"}'
root /bin/bash
bin /sbin/nologin
daemon /sbin/nologin
adm /sbin/nologin
lp /sbin/nologin
sync /bin/sync
shutdown /sbin/shutdown
halt /sbin/halt
mail /sbin/nologin
operator /sbin/nologin
end of file                            #执行完awk后再打印end of file


#统计包含root的行数 [root@localhost
~]# cat test | awk 'BEGIN{i=0}/root/{i++}END{print i}' #先执行BEGIN,赋值变量i=0,再匹配root的行,匹配到一次i+1,执行完所有模块再输出总次数 2 #BEGIN默认值为0,可以不定义变量初始值 [root@localhost ~]# cat test | awk '/root/{i++}END{print i}' 2

BEGIN和END后面必须加操作(anction)

3.7  总结awk执行过程

  回顾一下awk的结构

  awk -F 指定分隔符 ‘BRGIN{}END{}’,如下图

 

3.8  awk数组

  数组构成:

  数组名[元素名]=值

 

  如图不难发现,awk数组就和酒店一样。数组的名称就像是酒店名称,数组元素名称就像酒店房间号码,每个数组元素里面的内容就像是酒店房间里面的人。

#统计域名出现的次数
#准备文本文件
[root@localhost ~]# cat test
[root@ken ~]# cat test
http://www.qq.com/ken
http://www.qq.com/ken
http://www.qq.com/ken
http://www.qq.com/ken
http://www.qq.com/ken
http://www.qq.com/ken
http://www.qq.com/ken
http://www.sina.com/ken
http://www.sina.com/ken
http://www.sina.com/ken
http://www.sina.com/ken
http://www.sina.com/ken
http://www.sina.com/ken
http://www.sina.com/ken
http://www.sina.com/ken
http://www.sina.com/ken
http://www.sina.com/ken
http://www.sina.com/ken
http://www.sina.com/ken
http://www.sina.com/ken
http://www.taobao.com/ken
http://www.taobao.com/ken
http://www.taobao.com/ken
http://www.taobao.com/ken
http://www.taobao.com/ken
http://www.taobao.com/ken
http://www.taobao.com/ken
http://www.taobao.com/ken
http://www.taobao.com/ken
http://www.taobao.com/ken
http://www.taobao.com/ken
http://www.taobao.com/ken
http://www.taobao.com/ken
http://www.taobao.com/ken
http://www.taobao.com/ken
http://www.taobao.com/ken
http://www.taobao.com/ken
http://www.taobao.com/ken
http://www.taobao.com/ken
http://www.taobao.com/ken
http://www.taobao.com/ken
http://www.taobao.com/ken
http://www.taobao.com/ken
http://www.taobao.com/ken
http://www.taobao.com/ken
[root@localhost ~]# cat test  | awk -F "/+" '{print $2}'                                 #取出域名,以/ 分割分割时/不止一个,有两个在一块儿的(多个)
www.qq.com
www.qq.com
www.qq.com
www.qq.com
www.qq.com
www.qq.com
www.qq.com
www.sina.com
……..

[root@localhost ~]# cat test | awk -F "/+" '{zxj[$2]++}END{for (i in zxj){print i,zxj[i]}}'       #定义数组名为zxj,元素值为分割后的第二组,即域名每次找到相同的域名数组值加1。
 1
www.sina.com 13
www.qq.com 7
www.taobao.com 25

3.9 awk用法总结

  1) 结合内置变量,打印指定的几行,以及字段数量

  例子;输出有多余5个字段的行的第三个字段

    # cat a.sh | awk -F ":" 'NF>=5{print $3}'

  例子:输出每行行号和该行有几个字段

    # cat a.sh | awk -F ":" '{print NR,NF}'

 

  例子:输出用户名,要求所有用户显示在同一行,而且用空格分隔

    # cat mypwd | awk 'BEGIN{FS=":"; ORS=" "}{print $1}'

 

2) 结合正则来匹配一行或者某个字段

  例子:输出用户名以s为开头的用户的uid

    # cat mypwd | awk -F ":" '/^s/{print $}'

  例子:输出第五个字段是以t为结尾的用户的姓名

    # cat mypwd | awk -F ":" '$5~/t$/{print $1}'

 

3.)采用比较符号来进行打印指定的某些行

  例子:实现仅仅输出3-5的内容,每行前面添加一个行号

    # cat mypwd | awk 'NR>=3&&NR<=5{print NR,$1}'

  或

    # cat mypwd | awk 'NR==3,NR==5{print NR,$1}'

 

  例子:实现仅仅输出3 和 5 和 7行的内容,每行前面添加一个行号

    # cat mypwd | awk 'NR==3||NR==5||NR==7{print NR,$1}'

 

4.)END

  例子:统计mypwd中以#开头的行有多少行

    # cat mypwd | awk 'BEGIN{n=0}/^#/{n+=1}END{print n}'

 

  统计:mypwd中,以:为分隔符,字段数量在3-5的行的数目

    # cat mypwd  | awk 'BEGIN{FS=":"}NF>=3&&NF<=5{n+=1}END{print n}'

 

5)ip

  例子:统计IP

[root@localhost]# cat url.txt | awk -F "/+" '{urls[$2]++}END{for(key in urls)print key, urls[key]}’
www.baidu.com 12
haha.baidu.com 1
ftp.baidu.com 6
mail.baidu.com 7

 

猜你喜欢

转载自www.cnblogs.com/ajunyu/p/10894083.html