【亲测可用】Linux三剑客命令grep,sed,awk(cut)案例练习

目录

一、grep

1、grep常见命令

(1)-E :开启扩展(Extend)的正则表达式。

(2)-i :忽略大小写(ignore case)。

(3)-v :反过来(invert),只打印没有匹配的,而匹配的反而不打印。

(4)-n :显示行号

(5)-w :被匹配的文本只能是单词,而不能是单词中的某一部分,如文本中有liker,而我搜寻的只是like,就可以使用-w选项来避免匹配liker

(6)-c :显示总共有多少行被匹配到了,而不是显示被匹配到的内容,注意如果同时使用-cv选项是显示有多少行没有被匹配到。

(7)-o :只显示被模式匹配到的字符串。

(8)--color :将匹配到的内容以颜色高亮显示。

(9)-A  n:显示匹配到的字符串所在的行及其后n行,after

(10)-B  n:显示匹配到的字符串所在的行及其前n行,before

(11)-C  n:显示匹配到的字符串所在的行及其前后各n行,context

(12)[[:space:]] : 表示输出空格

2、grep操作实例

(1)显示所有包含San的行

(2)显示所有以J开始的人名所在的行

(3)显示所有以700结尾的行

(4)显示所有不包括834的行

(5)显示所有:12或/12的行

(6)显示所有电话号码的区号为408的行

(7)显示所有这样的行:它包含一个大写字母,后跟四个小写字母,一个逗号,一个空格,和一个大写字母

(8)显示包含一个小些字母,一个空格,最后一个字母是k或K的行

(9)显示工资为六位数的行,并在前面加行号

(10)显示包括Lincoln或lincoln的行,并且grep对大小写不敏感

二、sed

1、sed常见命令

(1)p表示print 

(2)d表示delete

(3)-n表示取消默认的完整输出,只要需要的

(4)-e是编辑命令。用于多个编辑任务

(5)-i表示修改文件内容

(6)=表示打印匹配行的行号

(7)-r命令是读命令。用于将一个文本文件中的内容加到当前文件的特定位置上

(8)-w是写入命令。

(9)r表示不需要转义。

(10)&符号在sed命令中代表上次匹配的结果

2、sed操作实例

(1)按给定格式输出,123abc456输出成456ABC123,再输出回123abc456

(1.1)123abc456输出成456ABC123

(1.2)456ABC123在返回输出成123abc456

  (1.3) sed的大小写变换(\u大写,\l小写,\b单词首字母)

(2)access22.log内容如下:

(2.1)只显示第3行/最后1行

(2.2)显示文件的第3行到第5行,并显示行号

(2.3)仅仅显示匹配字符串的行号

(2.4)打印匹配行的行号和内容【相当于后面又根据关键词查询了一次】

(2.5)获取含特定字符串(如:root),显示整行内容

(2.6)显示包含"hhh"的行到包含"omc"的行之间的行

(2.7)用world替换root【真实写入】

(2.8)在文件第一行添加happy,文件结尾添加new year

(2.9)& 符号在sed命令中代表上次匹配的结果 

(2.10)删除第3到第9行,只是不显示而已

(2.11)删除包含"hhh"的行到包含"omc"的行之间的行

(3)access23.log内容如下:

(3.1)把Jon的名字改成Jonathan

(3.2)删除头三行

(3.3)显示5-10行

(3.4)删除包含Lane的行

(3.5)显示所有生日在November-December之间的行

(3.6)把三个星号(***)添加到以Fred开头的行

(3.7)用JOSE HAS RETIRED取代包含Jose的行

(3.8)把Popeye的生日改成11/14/46

(3.9)删除所有空白行

三、cut与awk

1、awk常见命令

(1)概念:awk `参数` `pattern {action}` `filename`

(2)参数

(3)pattern

(4)action

(5)awk 内置变量,内置函数,运算符

2、awk操作实例

(1)根据域名进行计数排序处理(百度和搜狐)

方法1: cut -d -f

方法2: awk -F print

方法3: awk数组

方法4: cut与awk数组

方法5: grep

(2)打印最大版本号

(3)awk综合查询

(3.1)IF的用法,输出$为root

(3.2)计算平均数

(3.3)有重复行情况下的平均数

(3.4)统计空白行

(3.5)查找与替换

(3.6)匹配正则

(4)统计各ip/各用户的访问次数

(5)awk求和

(6)awk分类展示(腾讯)

(7)awk综合查询

(7.1)awk -F

(7.1.1)当分隔符只有一个字符时,分割符可以不用双引号或者单引号引住,也可以紧挨-F

(7.1.2)当分隔符有多个连续字符时,必须用双引号或者单引号引住分割符,可以紧挨-F,也可以有空格

(7.1.3)当有多个单独的分割符时,将多个分隔符写在中括号[]中

(7.2)awk使用内置变量,内置函数,运算符

(7.2.1)内置变量

(7.2.2)内置函数

(7.2.3)运算符

(7.2.3.1)逻辑非

(7.2.3.2)关系表达式

(7.2.3.3)模式匹配

(8)awk综合查询

(8.1)显示所有电话号码

(8.2)显示Dan的电话号码

(8.3)显示Susan的名字和电话号码

(8.4)显示所有以D开头的姓

(8.5)显示所有以一个C或E开头的名

(8.6)显示所有只有四个字符的名

(8.7)显示所有区号为916的人名

(8.8)显示Mike的捐款.显示每个值时都有以$开头.如$250$100$175

(8.9)显示姓,其后跟一个逗号和名,如Jody,Savage

(8.10)写一个awk的脚本


Linux 系统中,有三个强大的文本分析处理工具:grep  sed  awk,其中:grep用于搜索文本内容;sed用于编辑文本内容;awk用于处理和生成报表

一、grep

1、grep常见命令

(1)-E :开启扩展(Extend)的正则表达式。

(2)-i :忽略大小写(ignore case)。

(3)-v :反过来(invert),只打印没有匹配的,而匹配的反而不打印。

(4)-n :显示行号

(5)-w :被匹配的文本只能是单词,而不能是单词中的某一部分,如文本中有liker,而我搜寻的只是like,就可以使用-w选项来避免匹配liker

(6)-c :显示总共有多少行被匹配到了,而不是显示被匹配到的内容,注意如果同时使用-cv选项是显示有多少行没有被匹配到。

(7)-o :只显示被模式匹配到的字符串。

(8)--color :将匹配到的内容以颜色高亮显示。

(9)-A  n:显示匹配到的字符串所在的行及其后n行,after

(10)-B  n:显示匹配到的字符串所在的行及其前n行,before

(11)-C  n:显示匹配到的字符串所在的行及其前后各n行,context

(12)[[:space:]] : 表示输出空格

2、grep操作实例

文件:datafile
Steve Blenheim:238-923-7366:95 Latham Lane, Easton, PA 83755:11/12/56:20300
Betty Boop:245-836-8357:635 Cutesy Lane, Hollywood, CA 91464:6/23/23:14500
Igor Chevsky:385-375-8395:3567 Populus Place, Caldwell, NJ 23875:6/18/68:23400
Norma Corder:397-857-2735:74 Pine Street, Dearborn, MI 23874:3/28/45:245700
Jennifer Cowan:548-834-2348:583 Laurel Ave., Kingsville, TX 83745:10/1/35:58900
Jon DeLoach:408-253-3122:123 Park St., San Jose, CA 04086:7/25/53:85100
Karen Evich:284-758-2857:23 Edgecliff Place, Lincoln, NB 92086:7/25/53:85100
Karen Evich:284-758-2867:23 Edgecliff Place, Lincoln, NB 92743:11/3/35:58200
Karen Evich:284-758-2867:23 Edgecliff Place, Lincoln, NB 92743:11/3/35:58200
Fred Fardbarkle:674-843-1385:20 Parak Lane, DeLuth, MN 23850:4/12/23:780900
Fred Fardbarkle:674-843-1385:20 Parak Lane, DeLuth, MN 23850:4/12/23:780900
Lori Gortz:327-832-5728:3465 Mirlo Street, Peabody, MA 34756:10/2/65:35200
Paco Gutierrez:835-365-1284:454 Easy Street, Decatur, IL 75732:2/28/53:123500
Ephram Hardy:293-259-5395:235 CarltonLane, Joliet, IL 73858:8/12/20:56700
James Ikeda:834-938-8376:23445 Aster Ave., Allentown, NJ 83745:12/1/38:45000
Barbara Kertz:385-573-8326:832 Ponce Drive, Gary, IN 83756:12/1/46:268500
Lesley Kirstin:408-456-1234:4 Harvard Square, Boston, MA 02133:4/22/62:52600
William Kopf:846-836-2837:6937 Ware Road, Milton, PA 93756:9/21/46:43500
Sir Lancelot:837-835-8257:474 Camelot Boulevard, Bath, WY 28356:5/13/69:24500
Jesse Neal:408-233-8971:45 Rose Terrace, San Francisco, CA 92303:2/3/36:25000
Zippy Pinhead:834-823-8319:2356 Bizarro Ave., Farmount, IL 84357:1/1/67:89500
Arthur Putie:923-835-8745:23 Wimp Lane, Kensington, DL 38758:8/31/69:126000
Popeye Sailor:156-454-3322:945 Bluto Street, Anywhere, USA 29358:3/19/35:22350
Jose Santiago:385-898-8357:38 Fife Way, Abilene, TX 39673:1/5/58:95600
Tommy Savage:408-724-0140:1222 Oxbow Court, Sunnyvale, CA 94087:5/19/66:34200
Yukio Takeshida:387-827-1095:13 Uno Lane, Ashville, NC 23556:7/1/29:57000
Vinh Tranh:438-910-7449:8235 Maple Street, Wilmington, VM 29085:9/23/63:68900

(1)显示所有包含San的行

$ grep San datafile

(2)显示所有以J开始的人名所在的行

$ grep ^J datafile

(3)显示所有以700结尾的行

$ grep 700$ datafile

(4)显示所有不包括834的行

$ grep -v 834 datafile

(5)显示所有:12或/12的行

$ grep '[:/]12' datafile

(6)显示所有电话号码的区号为408的行

$ grep '408-' datafile

(7)显示所有这样的行:它包含一个大写字母,后跟四个小写字母,一个逗号,一个空格,和一个大写字母

$ grep '[A-Z][a-z]\{4,\},[[:space:]][A-Z]' datafile

其中,{}是特殊字符,需要写成\{\},否则将被视为字符{和}。空格用[[:space:]]

(8)显示包含一个小些字母,一个空格,最后一个字母是k或K的行

$ grep -i '[a-z][[:space:]]k' datafile

(9)显示工资为六位数的行,并在前面加行号

$ grep -n '[0-9]\{6,\}' datafile

(10)显示包括Lincoln或lincoln的行,并且grep对大小写不敏感

$ grep -i [Ll]incoln datafile

二、sed

1、sed常见命令

(1)p表示print 

(2)d表示delete

(3)-n表示取消默认的完整输出,只要需要的

(4)-e是编辑命令。用于多个编辑任务

(5)-i表示修改文件内容

(6)=表示打印匹配行的行号

(7)-r命令是读命令。用于将一个文本文件中的内容加到当前文件的特定位置上

(8)-w是写入命令。

(9)r表示不需要转义。

(10)&符号在sed命令中代表上次匹配的结果

其他详见:https://www.cnblogs.com/ftl1012/p/sed.html

2、sed操作实例

(1)按给定格式输出,123abc456输出成456ABC123,再输出回123abc456

access21.log如下:
123abc456
456def123
567abc789
789def567
要求输出:
456ABC123
123DEF456
789ABC567
567DEF789

(1.1)123abc456输出成456ABC123

#sed -r -i 's#(...)(.)(.)(.)(...)#\5\u\2\u\3\u\4\1#g' access21.log

(1.2)456ABC123在返回输出成123abc456

#sed -r -i 's#(...)(.)(.)(.)(...)#\5\l\2\l\3\l\4\1#g' access21.log
其中,sed中,使用\u表示大写,\l表示小写,\b表示单词首字母

  (1.3) sed的大小写变换(\u大写,\l小写,\b单词首字母)

access21-2.log内容是:we are family
1. 把所有小写变大写:
#sed 's#[a-z]#\u&#g' access21-2.log
WE ARE FAMMILY
2. 把每个单词的第一个小写字母变大写:
#sed 's#\b[a-z]#\u&#g' access21-2.log
We Are Fammily

(2)access22.log内容如下:

hhh     pts/1        192.168.25.1     Sat Jun 30 22:04   still logged in  
reboot   system boot  2.6.32-358.el6.i Sat Jun 30 22:04 - 22:43  (00:38)    
omc     pts/0        192.168.25.1     Sat Jun 30 20:16 - down   (00:00)    
reboot   system boot  2.6.32-358.el6.i Sat Jun 30 19:38 - 20:16  (00:37)    
root     pts/1        192.168.25.1     Sat Jun 30 12:20 - down   (00:55)    
root     pts/0        192.168.25.1     Sat Jun 30 11:53 - down   (01:22)    
reboot   system boot  2.6.32-358.el6.i Sat Jun 30 11:52 - 13:15  (01:23)    
root     pts/0        192.168.25.1     Sat Jun 30 05:40 - down   (02:51)    
reboot   system boot  2.6.32-358.el6.i Sat Jun 30 05:38 - 08:32  (02:54)    
root     pts/0        192.168.25.1     Fri Jun 29 21:01 - down   (06:21)    
 
wtmp begins Tue Jun  9 03:57:56 2015

(2.1)只显示第3行/最后1行

#sed -n '3p' access22.log
omc     pts/0        192.168.25.1     Sat Jun 30 20:16 - down   (00:00)
#sed -n '$p' access22.log
root     pts/0        192.168.25.1     Fri Jun 29 21:01 - down   (06:21)

(2.2)显示文件的第3行到第5行,并显示行号

#sed -n '3,5p' access22.log|sed =
1
omc     pts/0        192.168.25.1     Sat Jun 30 20:16 - down   (00:00)
2
reboot   system boot  2.6.32-358.el6.i Sat Jun 30 19:38 - 20:16  (00:37)
3
root     pts/1        192.168.25.1     Sat Jun 30 12:20 - down   (00:55)


(2.3)仅仅显示匹配字符串的行号

#sed -n '/root/=' access22.log
5
6
8
10

(2.4)打印匹配行的行号和内容【相当于后面又根据关键词查询了一次】

#sed -ne '/root/p' -e '/root/=' access22.log
root     pts/1        192.168.25.1     Sat Jun 30 12:20 - down   (00:55)
5
root     pts/0        192.168.25.1     Sat Jun 30 11:53 - down   (01:22)
6
root     pts/0        192.168.25.1     Sat Jun 30 05:40 - down   (02:51)
8
root     pts/0        192.168.25.1     Fri Jun 29 21:01 - down   (06:21)
10

(2.5)获取含特定字符串(如:root),显示整行内容

#sed -n '/root/p' access22.log
root     pts/1        192.168.25.1     Sat Jun 30 12:20 - down   (00:55)
root     pts/0        192.168.25.1     Sat Jun 30 11:53 - down   (01:22)
root     pts/0        192.168.25.1     Sat Jun 30 05:40 - down   (02:51)
root     pts/0        192.168.25.1     Fri Jun 29 21:01 - down   (06:21)


(2.6)显示包含"hhh"的行到包含"omc"的行之间的行

#sed -n '/hhh/,/omc/p' access22.log
hhh     pts/1        192.168.25.1     Sat Jun 30 22:04   still logged in
reboot   system boot  2.6.32-358.el6.i Sat Jun 30 22:04 - 22:43  (00:38)
omc     pts/0        192.168.25.1     Sat Jun 30 20:16 - down   (00:00)

(2.7)用world替换root【真实写入】

#sed -i '' 's/root/world/g' access22.log
注意:Mac 下sed命令报错:sed: 1: command a expects \ followed by text
在linux(centos等)环境中,执行sed -i 's/aaa/bbb/' test.txt,执行成功,但是在Mac中执行报错。
原因是Mac中用i命令进行替换时,强制要求备份 sed -i '一个路径' 's/aaa/bbb/' test.txt
如果不想备份,可以直接使用 sed -i '' 's/aaa/bbb/' test.txt,路径使用''单引号代替
s=search查找并替换, g=global全部替换。

(2.8)在文件第一行添加happy,文件结尾添加new year

sed -e '1i happy' -e '$a new year' access22.log       【界面显示】
sed -i -e '1i happy' -e '$a new year' access22.log    【真实写入文件】
在文件第一行和第四行的每行下面添加hahaha

(2.9)& 符号在sed命令中代表上次匹配的结果 

#sed '1,4i hahaha' access22.log

(2.10)删除第3到第9行,只是不显示而已

#sed 's/world/hello_&/g' access22.log

(2.11)删除包含"hhh"的行到包含"omc"的行之间的行

#sed '/hhh/,/omc/d' yum.log
删除包含"omc"的行到第十行的内容
#sed '/omc/,10d' yum.log
删除1到5行后,替换reboot为shutdown
#sed -e '1,5d' -e '=' -e 's/reboot/shutdown/g' access22.log  
打印3到6行的内容,并匹配reboot替换为shutdown
#sed -n -e '3,6p' -e 's/reboot/shutdown/g' access22.log
。。。。

(3)access23.log内容如下:

Steve Blenheim:238-923-7366:95 Latham Lane, Easton, PA 83755:11/12/56:20300
Betty Boop:245-836-8357:635 Cutesy Lane, Hollywood, CA 91464:6/23/23:14500
Igor Chevsky:385-375-8395:3567 Populus Place, Caldwell, NJ 23875:6/18/68:23400
Norma Corder:397-857-2735:74 Pine Street, Dearborn, MI 23874:3/28/45:245700
Jennifer Cowan:548-834-2348:583 Laurel Ave., Kingsville, TX 83745:10/1/35:58900
Jon DeLoach:408-253-3122:123 Park St., San Jose, CA 04086:7/25/53:85100
Karen Evich:284-758-2857:23 Edgecliff Place, Lincoln, NB 92086:7/25/53:85100
Karen Evich:284-758-2867:23 Edgecliff Place, Lincoln, NB 92743:11/3/35:58200
Karen Evich:284-758-2867:23 Edgecliff Place, Lincoln, NB 92743:11/3/35:58200
Fred Fardbarkle:674-843-1385:20 Parak Lane, DeLuth, MN 23850:4/12/23:780900
Fred Fardbarkle:674-843-1385:20 Parak Lane, DeLuth, MN 23850:4/12/23:780900
Lori Gortz:327-832-5728:3465 Mirlo Street, Peabody, MA 34756:10/2/65:35200
Paco Gutierrez:835-365-1284:454 Easy Street, Decatur, IL 75732:2/28/53:123500
Ephram Hardy:293-259-5395:235 CarltonLane, Joliet, IL 73858:8/12/20:56700
James Ikeda:834-938-8376:23445 Aster Ave., Allentown, NJ 83745:12/1/38:45000
Barbara Kertz:385-573-8326:832 Ponce Drive, Gary, IN 83756:12/1/46:268500
Lesley Kirstin:408-456-1234:4 Harvard Square, Boston, MA 02133:4/22/62:52600
William Kopf:846-836-2837:6937 Ware Road, Milton, PA 93756:9/21/46:43500
Sir Lancelot:837-835-8257:474 Camelot Boulevard, Bath, WY 28356:5/13/69:24500
Jesse Neal:408-233-8971:45 Rose Terrace, San Francisco, CA 92303:2/3/36:25000
Zippy Pinhead:834-823-8319:2356 Bizarro Ave., Farmount, IL 84357:1/1/67:89500
Arthur Putie:923-835-8745:23 Wimp Lane, Kensington, DL 38758:8/31/69:126000
Popeye Sailor:156-454-3322:945 Bluto Street, Anywhere, USA 29358:3/19/35:22350
Jose Santiago:385-898-8357:38 Fife Way, Abilene, TX 39673:1/5/58:95600
Tommy Savage:408-724-0140:1222 Oxbow Court, Sunnyvale, CA 94087:5/19/66:34200
Yukio Takeshida:387-827-1095:13 Uno Lane, Ashville, NC 23556:7/1/29:57000
Vinh Tranh:438-910-7449:8235 Maple Street, Wilmington, VM 29085:9/23/63:68900

(3.1)把Jon的名字改成Jonathan

$ sed -e 's/Jon/Jonathan/' datafile

(3.2)删除头三行

$ sed -e '1,3d' datafile

(3.3)显示5-10行

$ sed -n '5,10p' datafile

(3.4)删除包含Lane的行

$ sed -e '/Lane/d' datafile

(3.5)显示所有生日在November-December之间的行

$ sed -n '/:1[12]/p' datafile

(3.6)把三个星号(***)添加到以Fred开头的行

$ sed -e '/^Fred/s/Fred/***&/' datafile

(3.7)用JOSE HAS RETIRED取代包含Jose的行

$ sed -e '/Jose/s/.*/JOSEHASRETIRED/g' datafile

(3.8)把Popeye的生日改成11/14/46

三种写法:
(1)$ sed -e '/Popeye/s#3/19/35#/11/14/46#' access9.log
    其中,/Popeye/是查询含有Popeye的行,s#old#new 或者 s/old/new是字符串替换
(2)$ sed -e '/Popeye/s#[1-9]*/.*/.*#/11/14/46#' access9.log
(3)$ sed -e '/Popeye/s/[1-9]*\/.*\/.*:/11\/14\/46:/' access9.log

(3.9删除所有空白行

$ sed -e '/^$/d' datafile

三、cut与awk

1、awk常见命令

(1)概念:awk `参数` `pattern {action}` `filename`

这句命令的含义是:对于文件filename 的每一行,如果能够符合条件pattern,则执行动作action。如果不写pattern,则表示对于文件filename的每一行,都进行action 处理。

(2)参数

-F -F,其后跟一个分隔符或者正则表达式,其表示的意思是以怎样的规则对每一行进行分割。 默认是空格Tab键

(3)pattern

pattern 说明
/正则表达式/ 正则写在两个/ 之间
关系表达式 awk 中支持的关系运算符组成
模式匹配表达式 由 ~(匹配)和!~(不匹配)组成
BEGIN{语句} 在处理第一行文本之前,执行BEGIN 块中的语句,可以在这里进行一些变量初始化等操作
END{语句} 在处理完最后一行文本之后,执行END 块中的语句
/规则1/,/规则2/ 这是一个范围模板,只处理规则1第一次出现与规则2第一次出现之间的行

(4)action

print 用于输出

(5)awk 内置变量,内置函数,运算符

内置变量

$0,$n $0表示一整行内容;$n表示用分隔符隔开的第n列,$1表示第1列
NR,NF NR当前行数(第几行);NF当前行的列数(第几列);下标从1开始
FILENAME 当前文件名
FS 表示分隔符,类似-F 参数的功能
IGNORECASE 如果为真,表示忽略大小写进行匹配

内置函数

tolower(),toupper() $0表示一整行内容;$n表示用分隔符隔开的第n列,$1表示第1列
length(),split() length字符串长度;split字符串分割
rand() 随机数
systime(),strftime() systime是Unix时间戳;,strftime是时间格式化,用法同C语言中的strftime 函数
sin(),cos()    ,sqrt(),exp() sin正弦;cos余弦;sqrt平方根,exp求幂

运算符

+ - * / & 加;减;乘;除;求余
= += -= *= /= %= ^= **= 赋值运算符
< <= > >= != == 比较运算符
&&,||,! &&逻辑与;||逻辑与;!逻辑非
~,!~ ~匹配;!~不匹配

2、awk操作实例

(1)根据域名进行计数排序处理(百度和搜狐)

access1.log内容如下:

http://post.etiantian.org/index.html
http://www.etiantian.org/1.html
http://post.etiantian.org/index.html
http://mp3.etiantian.org/index.html
http://www.etiantian.org/3.html
http://post.etiantian.org/2.html

方法1: cut -d -f

#cut -d '/' -f 3 access1.log|sort|uniq -c|sort -r
(1)cut -d '/' -f 2,其中-d " "表示按照斜杠分割,-f 2表示取分割后的第2个cut中一般-d和-f配搭着用。
cut详细用法:https://www.jianshu.com/p/c3ad464281e2
(2)sort默认按照首字母升序,sort -r降序,
sort -n默认按照整个字符升序,sort -nr按照整个字符降序
sort -k:以哪个区间 (field) 来进行排序
区别详见:https://blog.csdn.net/znzxc/article/details/89534234
sort命令详见:https://www.jianshu.com/p/c4d159a98dd8
(3)uniq -c中unique是检查重复,-c是count,所以uniq -c表示统计重复的个数
uniq详细用法相见:https://www.runoob.com/linux/linux-comm-uniq.html 
一般而言,sort与uniq -c结合着用
分步骤看:
#cut -d '/' -f 3 access1.log |sort结果如下:
mp3.etiantian.org
post.etiantian.org
post.etiantian.org
post.etiantian.org
www.etiantian.org
www.etiantian.org

#cut -d '/' -f 3 access1.log |sort|uniq -c
1 mp3.etiantian.org
3 post.etiantian.org
2 www.etiantian.org

#cut -d '/' -f 3 access1.log |sort|uniq -c|sort -r
3 post.etiantian.org
2 www.etiantian.org
1 mp3.etiantian.org


方法2: awk -F print

#awk -F '/' '{print $3}' access1.log|sort|uniq -c|sort -r
说明:cut -d '/' -f 3 access1.log 等价于 awk -F "/" '{print $3}' access1.log


方法3: awk数组

#awk -F '/' '{++arr[$3]}END{for(key in arr) print arr[key],key}' access1.log|sort -k1 -r


方法4: cut与awk数组

#cut -d '/' -f 3 access1.log|awk '{++arr[$1]}END{for(key in arr) print arr[key],key}'|sort -k1 -r
其中,sort -k1表示按照第1个(第1个是个数)来排序(linux从1开始),-r表示降序


方法5: grep

#cat access1.log |tr "\/" "\n"|grep etiantian|sort|uniq -c|sort -r

其他方法详见:https://blog.51cto.com/aqiang/1891886


(2)打印最大版本号

已知access2.log,第一列是文件名,第二列是版本号,打印出每个文件最大的版本号一行。

# awk '{print}' access2.log
file 100
dir 11
file 100
dir 11
file 102
dir 112
file 120
dir 119
解答如下:
#awk '{if(arr[$1]<$2) arr[$1]=$2}END{for(i in arr) print i,arr[i]}' access2.log|sort -k2 -r
file 120
dir 119


(3)awk综合查询

access3.log内容如下:

a+b.sh,2,3,4,5
awk,2,3,4,5
case.sh,2,3,4,5
for.sh,2,3,4,5
grep.all,2,3,4,5
if.sh,2,3,4,5
param.sh,2,3,4,5
sed,2,3,4,5
test,2,3,4,5
while.sh,2,3,4,5
a+b.sh,2,3,4,5
awk,2,3,4,5
case.sh,2,3,4,5
for.sh,2,3,4,5
grep.all,2,3,4,5
if.sh,2,3,4,5
param.sh,2,3,4,5
sed,2,3,4,5
test,2,3,4,5
while.sh,2,3,4,5

(3.1)IF的用法,输出$为root

#awk -F ',' '{if($1=="while.sh"){print $0}}' access3.log

(3.2)计算平均数

#awk -F ',' '{total=$2+$3+$4+$5;avg=total/4}{print $1,avg}' access3.log

(3.3)有重复行情况下的平均数

#awk -F',' '{total=$2+$3+$4+$5;avg=total/4;arr[$1]+=avg;count[$1]++}END{for(i in arr) {print i,arr[i]/count[i]}}' access3.log

(3.4)统计空白行

#awk '/^$/{print x+=1}' access3.log

(3.5)查找与替换

#awk -F',' '{gsub(/while.sh/,"zhang san",$0)}{print $0}' access3.log >access3.log

(3.6)匹配正则

#awk -F':' '$0!~/root/{print $0}' /etc/passwd


(4)统计各ip/各用户的访问次数

access4.log内容如下:

1.2.3.4 - - [04/May/2018:09:26:09 +0800] "POST /XXX/login.htm HTTP/1.1" 200 896 "0.009" "okhttp/3.9.1" "userName=zhuzi&password=z13y14Bao&uniqueCode=88888888"
2.3.4.5 - - [04/May/2018:09:26:09 +0800] "POST /XXX/login.htm HTTP/1.1" 200 887 "0.010" "okhttp/3.9.1" "userName=zi&password=z13y14Bao&uniqueCode=99999999"
3.2.3.4 - - [04/May/2018:09:26:09 +0800] "POST /XXX/login.htm HTTP/1.1" 200 896 "0.009" "okhttp/3.9.1" "userName=haiyang&password=21131409oui&uniqueCode=11111111"
4.3.4.5 - - [04/May/2018:09:26:09 +0800] "POST /XXX/login.htm HTTP/1.1" 200 887 "0.010" "okhttp/3.9.1" "userName=anya&password=213sdfasdf&uniqueCode=44444444"
4.3.4.5 - - [04/May/2018:09:26:09 +0800] "POST /XXX/login.htm HTTP/1.1" 200 887 "0.010" "okhttp/3.9.1" "userName=anya&password=213sdfasdf&uniqueCode=44444444"
(1)统计各个ip的访问次数
#cat access4.log|awk '{arr[$1]+=1}END{for(i in arr)print arr[i],i}'|sort -t ' ' -k1 -nr
2 4.3.4.5
1 3.2.3.4
1 2.3.4.5
1 1.2.3.4

(2)用户的唯一标识是uniqueCode,统计各用户的访问次数
#grep 'uniqueCode' access4.log | awk -F '&' '{if(index($NF, "uniqueCode")>0) arr[substr($NF,12,8)]++;}END{for(i in arr){print arr[i],i}}'|sort -k1 -nr
2 44444444
1 99999999
1 88888888
1 11111111
其中,$NF=3,linux中下标从1开始,如下(a)等价于(b)
(a): #grep 'uniqueCode' access4.log | awk -F '&' '{for(x=1;x<=NF;x++)if(index($x, "uniqueCode")>0){print substr($x,12,8); break}}'
(b): #grep 'uniqueCode' access4.log | awk -F '&' '{if(index($NF, "uniqueCode")>0) print substr($NF,12,8)}'

(5)awk求和

假设access6.log文件内容如下:

100
a 100
b -50
c -20
d -30

要求输出结果1:
100
a 100
200
b -50
150
c -20
130
d -30

要求输出结果2:
100
a 100
200
b -50
150
c -20
130
d -30

100

(1)结果1: #awk 'sum+=$1+$2{if(NR==1) print $1;else if(NR==5)print $0;else print $1"\t"$2"\n"sum}' access5.log
(2)结果2: #awk 'sum+=$1+$2{if(NR==1) print $1;else print $1"\t"$2"\n"sum}' access5.log

(6)awk分类展示(腾讯)

假设access6.log文件内容如下:
12334:13510014336
12345:12334555666
12334:12343453453
12099:13598989899
12334:12345454545
12099:12343454544
分类如下:
[12334]
13510014336
12343453453
...........
[12099]
13598989899
12343454544

解答:#cat access6.log | sort -r | awk -F: '{if (tmp!=$1) {tmp=$1;print "["tmp"]"} print $2}'

(7)awk综合查询

access7.log内容如下:
小明,男,23,550^优秀---北京
小丽,女,22,560^优秀---河北
小磊,男,24,530^良好---河南
小召,男,23,540^优良---山东
小欣,女,23,545^优良---山西

(7.1)awk -F

(7.1.1)当分隔符只有一个字符时,分割符可以不用双引号或者单引号引住,也可以紧挨-F

#awk -F, '{print $1,$2,$3}' access7.log      #`分隔符`紧挨着`-F`
#awk -F , '{print $1,$2,$3}' access7.log     #`分隔符`与`-F`之间有一个空格
#awk -F',' '{print $1,$2,$3}' access7.log    #`分隔符`用单引号引住,并且紧挨`-F`
#awk -F"," '{print $1,$2,$3}' access7.log    #`分隔符`用双引号引住,并且紧挨`-F`
#awk -F ',' '{print $1,$2,$3}' access7.log   #`分隔符`用单引号引住,与`-F`之间有空格
#awk -F "," '{print $1,$2,$3}' access7.log   #`分隔符`用双引号引住,与`-F`之间有空格

(7.1.2)当分隔符有多个连续字符时,必须用双引号或者单引号引住分割符,可以紧挨-F,也可以有空格

#awk -F '---' '{print $2}' access7.log   #`分隔符`用单引号引住,与`-F`之间有空格
#awk -F"---" '{print $5}' access7.log    #`分隔符`用双引号引住,与`-F`之间没有空格

(7.1.3)当有多个单独的分割符时,将多个分隔符写在中括号[]中

如下,表示以, 或者以--- 为分隔符

#awk -F "[,^]" '{print $1, $2, $3, $4, $5}' access7.log

(7.2)awk使用内置变量,内置函数,运算符

(7.2.1)内置变量

#awk -F"---" '{print NR, $1, $2, NF, FILENAME}' access7.log
1 小明,男,23,550^优秀 北京 2 access7.log
2 小丽,女,22,560^优秀 河北 2 access7.log
3 小磊,男,24,530^良好 河南 2 access7.log
4 小召,男,23,540^优良 山东 2 access7.log
5 小欣,女,23,545^优良 山西 2 access7.log

(7.2.2)内置函数

#awk -F"---" '{print NR"|"$1"|"$2"|"NF"|"FILENAME"|"systime()}' log.txt
1|小明,男,23,550^优秀|北京|2|access7.log|1587022443
2|小丽,女,22,560^优秀|河北|2|access7.log|1587022443
3|小磊,男,24,530^良好|河南|2|access7.log|1587022443
4|小召,男,23,540^优良|山东|2|access7.log|1587022443
5|小欣,女,23,545^优良|山西|2|access7.log|1587022443

(7.2.3)运算符

(7.2.3.1)逻辑非

输出不为男的学生信息 #awk '!/男/ {print NR"|"$0}' access7.log
2|小丽,女,22,560^优秀---河北
5|小欣,女,23,545^优良---山西

(7.2.3.2)关系表达式

输出年龄为23的学生信息:#awk -F, '$3==23 {print $3, $0}' access7.log
输出年龄为23或25的学生信息 #awk -F, '$3==23 || $3==25' access7.log
输出年龄为22的学生信息 #awk -F, '{if($3==22) print $3, $0}' access7.log
输出奇数行 #awk -F, 'NR%2==1 {print NR, $0}' access7.log

(7.2.3.3)模式匹配

输出年龄为24的学生信息:#awk -F, '$3 ~/24/ {print $3, $0}' access7.log

(8)awk综合查询

access38.log文件内容如下:
Mike Harrington:[510] 548-1278:250:100:175
Christian Dobbins:[408] 538-2358:155:90:201
Susan Dalsass:[206] 654-6279:250:60:50
Archie McNichol:[206] 548-1348:250:100:175
Jody Savage:[206] 548-1278:15:188:150
Guy Quigley:[916] 343-6410:250:100:175
Dan Savage:[406] 298-7744:450:300:275
Nancy McNeil:[206] 548-1278:250:80:75
John Goldenrod:[916] 348-4278:250:100:175
Chet Main:[510] 548-5258:50:95:135
Tom Savage:[408] 926-3456:250:168:200
Elizabeth Stachelin:[916] 440-1763:175:75:300
上面的数据库中包含名字,电话号码和过去三个月里的捐款

(8.1)显示所有电话号码

$ awk -F: '{print $2}' access38.log
[510] 548-1278
[408] 538-2358
......

(8.2)显示Dan的电话号码

$ awk -F: '$1~/^Dan/{print $2}' access38.log
[406] 298-7744

(8.3)显示Susan的名字和电话号码

$ awk -F: '$1~/^Susan/{print $1":"$2}' access38.log
Susan Dalsass:[206] 654-6279

(8.4)显示所有以D开头的姓

$ awk -F"[: ]" '$2~/^D/{print $2}' access38.log
Dobbins
Dalsass

(8.5)显示所有以一个C或E开头的名

$ awk -F"[: ]" '$1~/^C|E/{print $1}' access38.log
Christian
Chet
Elizabeth

(8.6)显示所有只有四个字符的名

$ awk 'length($1)==4{print $1}' access38.log
Mike
Jody
John
Chet

(8.7)显示所有区号为916的人名

$ awk -F"[: ]" '$3~/916916/{print $1,$2}' access38.log

Guy Quigley
John Goldenrod
Elizabeth Stachelin

$ awk -F"[: ]" '$3~/\[916916\]/{print $1"\t"$2"\t"$3}'access38.log

如果想要以[916]作为查询条件,[]需要写成

(8.8)显示Mike的捐款.显示每个值时都有以$开头.如$250$100$175

$ awk -F"[: ]" '$1~/Mike/{print "$"$5,"$"$6,"$"$7}' access38.log
$250 $100 $175

逗号实际上是对应OFS的值的,即这样规定逗号对应输出字段分割符的值, 默认的OFS的值为空格,即输出代码中的逗号对应输出显示中的空格。有逗号和没有逗号是有区别的: 
echo "a b c" | awk '{print $1,$2,$3}' 命令返回值:a b c 
echo "a b c" | awk '{print $1 $2 $3}' 命令返回值:abc

awk中直接使用空白:[[:blank:]]。
综上:,和[[:blank:]]都表示空格

(8.9)显示姓,其后跟一个逗号和名,如Jody,Savage

$ awk -F"[: ]" '{print $2","$1}' access38.log
Harrington,Mike
Dobbins,Christian
Dalsass,Susan
McNichol,Archie
Savage,Jody
Quigley,Guy
Savage,Dan
McNeil,Nancy
Goldenrod,John
Main,Chet
Savage,Tom
Stachelin,Elizabeth

(8.10)写一个awk的脚本

显示Savage的全名和电话号码
.显示Chet的捐款
.显示所有头一个月捐款$250的人名.
注:区号本来是圆括号表示的.
#!/bin/awk -f
$1~/Savage/{print $1":"$2}
$1~/Chet/{print $3,$4,$5}
$3~/250/{print $1}
结果显示比较乱。
脚本实现为:
#!/bin/sh
awk -F: '$1~/Savage/{print $1":"$2}' datafile > tmp
awk -F: '$1~/Chet/{print $3,$4,$5}'datafile >> tmp
awk -F: '$3~/250/{print $1}' datafile >> tmp
cat tmp
rm tmp
这样显示比较整齐。


转载:
https://blog.51cto.com/aqiang/1891886
https://blog.csdn.net/magic_wz/java/article/details/8472699
https://www.cnblogs.com/zhuzi91/p/8989598.html
https://www.cnblogs.com/lyqlyqlyq/p/11489904.html
https://www.cnblogs.com/paul8339/p/6207182.html

https://www.jianshu.com/p/67d7b3056777 awk命令
https://www.cnblogs.com/ftl1012/p/sed.html sed命令

猜你喜欢

转载自blog.csdn.net/wuhuagu_wuhuaguo/article/details/107499095