第1章 linux系统三剑客
1.1 【grep/egrep】
[root@wangyoukun scripts]# grep IPADDR /etc/sysconfig/network-scripts/ifcfg-eth0
IPADDR=10.0.0.200
[root@wangyoukun scripts]# grep "IPADDR|DNS1" /etc/sysconfig/network-scripts/ifcfg-eth0
[root@wangyoukun scripts]# egrep "IPADDR|DNS1" /etc/sysconfig/network-scripts/ifcfg-eth0
IPADDR=10.0.0.200
DNS1=223.5.5.5
[root@wangyoukun ~]# chkconfig |grep sshd
sshd 0:off 1:off 2:on 3:on 4:on 5:on 6:off
[root@wangyoukun ~]# chkconfig |grep "sshd|network"
[root@wangyoukun ~]# chkconfig |egrep "sshd|network"
network 0:off 1:off 2:on 3:on 4:on 5:on 6:off
sshd 0:off 1:off 2:on 3:on 4:on 5:on 6:off
第2章 sed 的用法
2.1 命令作用:
sed是Stream Editor(字符流编辑器)的缩写,简称流编辑器。Sed命令是操作、过滤和转换文本内容的强大工具。常用功能有增(增加)删(删除)改(修改)查(查询),其中查询最常用的两大功能是过滤(过滤指定字符串),取行(取出指定行)。
我们现在学习的sed版本是GNU开源版本的,我们的实验环境是Centos6.7系统,内核版本是2.6.32-642.el6.x86_64。
[root@oldboy35-edu ~]# cat /etc/redhat-release
CentOS release 6.8 (Final)
[root@oldboy35-edu ~]# uname -r
2.6.32-642.el6.x86_64
[root@oldboy35-edu ~]# sed –version #查看sed软件版本
GNU sed version 4.2.1
…………省略若干行
语法格式:
sed [options] [sed-commands] [input-file]
sed [选项] [sed命令] [输入文件]
2.2 命令执行流程:
sed软件从文件或管道中读取一行,处理一行,输出一行;然后在读取一行,处理一行,再输出一行····
参数选项说明:
options[选项] |
解释说明(带※为重点) |
-n |
取消默认的sed软件的输出,常与sed命令的p连用。※※※ |
-e |
一行命令语句可以执行多条sed命令 |
-f |
选项后面可以接sed脚本的文件名 |
-r |
使用扩展正则表达式,默认情况sed只识别基本正则表达式。※※※ |
-i |
直接修改文件内容,而不是输出终端。不用就不会修改文件内容和数据。※※※ |
[sed 命令] |
解释说明(带※为重点) |
a |
追加,在指定行后添加一行和多行文本。※※※ |
c |
取代指定的行 |
d |
删除指定的行。s/xxx/d※※※ |
D |
删除模式空间的部分内容,直到遇到换行符\n结束操作,与多行模式相关 |
i |
插入,在指定行前添加一行或多行文本。※※※ |
h |
把模式空间的内容复制到保持空间。 |
H |
把模式空间的内容追加到保持空间。 |
g |
把保持空间的内容复制到模式空间。 |
G |
把保持空间的内容追加到模式空间。 |
x |
交换模式空间和保持空间的内容。 |
l |
打印不可见的字符。 |
n |
清空模式空间的内容并读入下一行。 |
N |
不清空模式空间,并读取下一行数据并追加到模式空间。※※※ |
p |
打印模式空间的内容,通常p会与选项-n一起使用。※※※ |
q |
退出sed. |
r |
从指定文件读取数据。 |
s |
取代,s#old#new#gè这里的g是s命令的替代标志,注意和g命令区分。※※※ |
w |
另存,把模式空间的内容保存到文件中。 |
y |
根据对应位置转换字符。 |
:lable |
定义一个标签。 |
b lable |
执行该标签后面的命令 |
t |
如果前面的命令执行成功,那么就跳到t指定的标签处,继续往下执行后续命令 |
特殊符号 |
解释说明(带※为重点) |
$ |
匹配最后一行 |
! |
对指定行意外的所有行应用命令。※※※ |
= |
打印当前行号。※※※ |
~ |
表示从First行开始,以步长Step递增。 |
& |
代表被替换的内容。 |
; |
实行一行命令语句可以执行多条sed命令。Sed ‘2a A;B;C’※※※ |
{} |
对单个地址或地址范围执行批量操作。 |
+ |
地址范围中用到的符号,做加法运算。 |
2.3 使用范例:
[root@oldboy35-edu ~]# cat >person.txt <<EOF 实验文本
> 101,oldboy,CEO
> 102,zhangyao,CTO
> 103,alex,COO
> 104,yy,CFO
> 105,feixue,CIO
> EOF
[root@oldboy35-edu ~]# cat person.txt
101,oldboy,CEO
102,zhangyao,CTO
103,alex,COO
104,yy,CFO
105,feixue,CIO
2.3.1 增 往文件指定位置追加或插入文本 (单行增加)
[root@oldboy35-edu ~]# sed '2a 106,dandn,CSO' person.txt 将文本追加到第二行行后
101,oldboy,CEO
102,zhangyao,CTO
106,dandn,CSO
103,alex,COO
104,yy,CFO
105,feixue,CIO
[root@oldboy35-edu ~]# sed '2i 106,dandan,CSO' person.txt 插入文本到第二行行前
101,oldboy,CEO
106,dandan,CSO
102,zhangyao,CTO
103,alex,COO
104,yy,CFO
105,feixue,CIO
往文件指定位置追加或插入文本 (多行增加)
[root@oldboy35-edu ~]# sed '2a 106,dandan,CSO\n107,bingbing,CCO' person.txt
101,oldboy,CEO (这里通过\n可以把不同内容以回车方式多行增加到文本)
102,zhangyao,CTO
106,dandan,CSO
107,bingbing,CCO
103,alex,COO
104,yy,CFO
105,feixue,CIO
企业案例题1:优化ssh配置(一键完成增加若干参数)
在我们学习Centos系统优化时,有一个优化点:更改ssh服务远程登录的配置。主要的操作是在ssh的配置文件/etc/ssh/sshd_config加入下面5行文本。
Port 52113
PermitRootLogin no
PermitEmptPassword no
UseDNS no
GSSAPIAuthentication no
当然我们可以使用vi/vim命令编辑这个文本,但这样就比较麻烦,现在想用一条命令增加5行文本到第13行前。注意:修改前别忘了备份配置文件:cp /etc/ssh/sshd_config{,.ori} cp /etc/ssh/sshd_config.ori /etc/ssh/sshd_config(可进行恢复)
cp /etc/ssh/sshd_config{,.ori} 先对文件进行备份
sed -i “12a Port 52113\nPermitRoot no\nPermitEmtyPassswords no\nUseDNS no\nGSSAPTIAuthentication no" /etc/ssh/sshd_config(用sed命令多行追加功能就可以搞定)
命令说明:题目要求在第13行前插入,13i,当然也就是第12后,12a。最后插入5行内容,用“\n”就可以变成一行了。注意:“-i”这个选项能够实际的修改文件内容,在练习时可以去掉,防止改掉了配置文件。如果使用了“-i”,可以使用备份文件还原。生产环境修改配置文件那就需要-i选项了。
sed –n ’13,17p’ /etc/ssh/sshd_config 可查看是否添加成功
2.3.2 删 d 删除文本
[root@oldboy35-edu ~]# cat person.txt
101,oldboy,CEO
102,zhangyao,CTO
103,alex,COO
104,yy,CFO
105,feixue,CIO
[root@oldboy35-edu ~]# sed '1~2d' person.txt (删除1、3、5奇数行)
102,zhangyao,CTO
104,yy,CFO
[root@oldboy35-edu ~]# sed '2~2d' person.txt (删除2、4偶数行)
101,oldboy,CEO
103,alex,COO
105,feixue,CIO
企业案例2:打印文件内容但不包含oldboy
[root@oldboy35-edu ~]# sed '/oldboy/d' person.txt (删除oldboy这一行)
102,zhangyao,CTO
103,alex,COO
104,yy,CFO
105,feixue,CIO
[root@oldboy35-edu ~]# sed '/oldboy/!d' person.txt (删除非oldboy这一行)
101,oldboy,CEO
[root@oldboy35-edu ~]# sed '2,3d' person.txt (删除2、3行)
101,oldboy,CEO
104,yy,CFO
105,feixue,CIO
[root@oldboy35-edu ~]# sed '2,3!d' person.txt (不删除2、3行)
102,zhangyao,CTO
103,alex,COO
2.3.3 改 按行替换 C用新行取代旧行 c即change
[root@oldboy35-edu ~]# sed '2c 106,dandan.CSO' person.txt
101,oldboy,CEO
106,dandan.CSO
103,alex,COO
104,yy,CFO
105,feixue,CIO
[root@oldboyedu-35 ~]# sed -i 's#zhangyao#dandan#g' person.txt(替换文本)
[root@oldboyedu-35 ~]# cat person.txt
101,oldboy,CEO
102,dandan,CTO
103,Alex,COO
104,yy,CFO
105,feixue,CIO
[root@oldboyedu-35 ~]# sed -i 's#dandan#zhangyao#g' person.txt
[root@oldboyedu-35 ~]# cat person.txt
101,oldboy,CEO
102,zhangyao,CTO
103,Alex,COO
104,yy,CFO
105,feixue,CIO
企业案例3:指定行进行修改:
[root@oldboy35-edu ~]# sed '3s#0#9#g' person.txt
101,oldboy,CEO
102,zhangyao,CTO
193,alex,COO (只将第三行0换成9)
104,yy,CFO
105,feixue,CIO
双引号把变量解析出来,单引号所见即所得,反引号则跟命令搭配使用
[root@oldboy35-edu ~]# sed 's#oldboy#$LANG#' person.txt
101,$LANG,CEO
102,ZHANGYAO,CTO
103,alex,COO
104,yy,CFO
105,feixue,CIO
[root@oldboy35-edu ~]# sed "s#oldboy#$LANG#" person.txt
101,en_US.UTF-8,CEO
102,ZHANGYAO,CTO
103,alex,COO
104,yy,CFO
105,feixue,CIO
分组替换: \(\)和\1
[root@oldboy35-edu ~]# echo "I am oldboy teacher."|sed -r 's#^.*am (.*) t.*$#\1#g'
oldboy
[root@oldboy35-edu ~]# echo "I am oldboy teacher."|sed 's#^.*am \([a-z].*\) t.*$#\1#g'
Oldboy
[root@oldboy35-edu ~]# echo "I am oldboy teacher."|sed -r 's#I (.*)(.*) tea.*$#\1\2#g'
am oldboy
取IP方案实例:
[root@oldboy35-edu ~]# ifconfig eth0|sed -rn '2s#^.*dr:(.*) Bc.*$#\1#gp'
192.168.56.128
企业案例4:系统开机自启动优化
[root@oldboy35-edu ~]# chkconfig|egrep -v "sshd|network|rsyslog|crond|sysstat"|awk '{print $1}'|sed -r 's#(.*)#chkconfig \1 off#g'|bash 或sed ‘s#.*#chkconfig & off#g’ (bash可以换成在g后加e)
[root@oldboy35-edu ~]# chkconfig|egrep -v "sshd|network|rsyslog|crond|sysstat"|awk '{print "chkconfig",$1,"off"}'|bash
[root@oldboy35-edu ~]# chkconfig |awk '!/sshd|network|rsyslog|sysstat/ {print "chkconfig",$1,"off"}'|bash
grep –ve “sshd|network|rsyslog|crond|sysstat”将我们保留的启动项取反排除。
awk '{print $1}' 使用awk把开机启动项名称取出来。
sed -r 's#(.*)#chkconfig \1 off#g'拼凑命令,“\1”代表前面^(.*)匹配的内容即开机启动的项目名称。
特殊符号&代表被替换的内容
&在适合的场景使用特别方便,用特殊符号“&”与分组替换一起使用,进行对比。
[root@oldboy35-edu ~]# cat person.txt
101,oldboy,CEO
102,ZHANGYAO,CTO
103,alex,COO
104,yy,CFO
105,feixue,CIO
[root@oldboy35-edu ~]# sed -r 's#(.*),(.*),(.*)#&----------- \1 \2 \3#' person.txt
101,oldboy,CEO----------- 101 oldboy CEO
102,ZHANGYAO,CTO----------- 102 ZHANGYAO CTO
103,alex,COO----------- 103 alex COO
104,yy,CFO----------- 104 yy CFO
105,feixue,CIO----------- 105 feixue CIO
这里将分组替换和&符号放在一起对比。命令中的分组替换使用了3个小括号,每个小括号分别代表每一行以逗号作为分隔符的每一列。上面的&符即代表每一行,即模型中’s#▆#▲#g’的▆。
企业案例5:批量重命名文件
当前目录下有文件如下所示:
[root@oldboy35-edu test]# ls
stu_102999_1_finished.jpg stu_102999_3_finished.jpg stu_102999_5_finished.jpg
stu_102999_2_finished.jpg stu_102999_4_finished.jpg
要求用sed命令重命名,效果为:
stu_102999_1.jpg stu_102999_2.jpg stu_102999_3.jpg stu_102999_4.jpg stu_102999_5.jpg
用sed –r ‘s###g’
[root@oldboy35-edu test]# ls *jpg|sed -r 's#(.*)_finished(.*)#mv & \1\2 #g'|bash
[root@oldboy35-edu test]# ls *jpg
stu_102999_1.jpg stu_102999_2.jpg stu_102999_3.jpg stu_102999_4.jpg stu_102999_5.jpg
用rename重命名
[root@oldboy35-edu test]# ls *jpg
stu_102999_1.jpg stu_102999_2.jpg stu_102999_3.jpg stu_102999_4.jpg stu_102999_5.jpg
[root@oldboy35-edu test]# rename jpg JPG *
[root@oldboy35-edu test]# ls
stu_102999_1.JPG stu_102999_2.JPG stu_102999_3.JPG stu_102999_4.JPG stu_102999_5.JPG test.txt
[root@oldboy35-edu test]# rename .JPG -`date +%F`.JPG *
[root@oldboy35-edu test]# ls
stu_102999_1-2017-04-14.JPG stu_102999_3-2017-04-14.JPG stu_102999_5-2017-04-14.JPG
stu_102999_2-2017-04-14.JPG stu_102999_4-2017-04-14.JPG
修改文件:
[root@oldboy35-edu ~]# sed -i.ori 's#ZHANGYAO#MB#' person.txt
[root@oldboy35-edu ~]# cat person.txt
101,oldboy,CEO
102,MB,CTO
103,alex,COO
104,yy,CFO
105,feixue,CIO
[root@oldboy35-edu ~]# cat person.txt.ori
101,oldboy,CEO
102,ZHANGYAO,CTO
103,alex,COO
104,yy,CFO
105,feixue,CIO
命令说明:使用person.txt.ori还原文件
[root@oldboy35-edu ~]# sed 'w opt.txt' person.txt
101,oldboy,CEO
102,zhangyao,CTO
103,alex,COO
104,yy,CFO
105,feixue,CIO
[root@oldboy35-edu ~]# cat opt.txt
101,oldboy,CEO
102,zhangyao,CTO
103,alex,COO
104,yy,CFO
105,feixue,CIO
命令w可以把当前模式空间的内容保存到文件中。选项-i是直接修改源文件。默认情况下模式空间的内容每次都会打印到标准输出(屏幕),如果要把输出内容保存到文件同时不显示屏幕上,还需要使用-n选项取消默认输出
2.3.4 查 p
“p”:输出指定内容,但默认会输出2次匹配的结果,因此使用-n选项取消默认输出,记忆方法:p 即print,意思是打印。
[root@oldboy35-edu ~]# sed 'p' person.txt
101,oldboy,CEO
101,oldboy,CEO
102,zhangyao,CTO
102,zhangyao,CTO
103,alex,COO
103,alex,COO
104,yy,CFO
104,yy,CFO
105,feixue,CIO
105,feixue,CIO
[root@oldboy35-edu ~]# sed -n 'p' person.txt 取消默认输出
101,oldboy,CEO
102,zhangyao,CTO
103,alex,COO
104,yy,CFO
105,feixue,CIO
[root@oldboy35-edu ~]# sed -n '2p' person.txt 显示第二行
102,ZHANGYAO,CTO
[root@oldboy35-edu ~]# sed -n '/oldboy/p' person.txt
101,oldboy,CEO
过滤多个字符
[root@oldboy35-edu ~]# sed -rn '/oldboy|yy/p' person.txt
101,oldboy,CEO
104,yy,CFO
命令说明:使用扩展正则“|”,为了不使用转义符号“\”,因此使用-r选项开启扩展正则表达式模式。
2.4 sed软件替换命令详解
sed ‘[address-range|pattern-range] s#original-string#replacement-string#[substitute-flags]’ [input file]
sed’[地址范围|模式范围]s#[被替换的字符串]#[替换后的字符串]#[替换的标志]’[输入文件]
[root@oldboy35-edu ~]# cat person.txt
101,oldboy,CEO
102,MB,CTO
103,Alex,COO
104,yy,CFO
105,feixue,CIO
[root@oldboyedu-35 ~]# sed 's#alex#NB#i' person.txt 使用i来忽略大小写
101,oldboy,CEO
102,zhangyao,CTO
103,NB,COO
104,yy,CFO
105,feixue,CIO
Ms# # #Ng的使用
●Msà对第M行处理,无g替换标志,只处理第一处匹配,有g替换标志则对第M行全部替换。
●Ngà对每一行,从第N行开始替换。
●Ms、Ng合用表示只对第M行从第N行匹配开始替换
[root@oldboy35-edu ~]# sed '2s#1#0#g' a.txt 有g替换标志则对第2行全部替换
1 1 1 1 1
0 0 0 0 0
1 1 1 1 1
1 1 1 1 1
1 1 1 1 1
[root@oldboy35-edu ~]# sed '3s#1#0#2' a.txt对第三行的第二个字符进行替换
1 1 1 1 1
1 1 1 1 1
1 0 1 1 1
1 1 1 1 1
1 1 1 1 1
打印标志:p
打印标志p,当替换操作完成后,打印替换后的行,与选项-n连用。这里的p是附属于sed命令s的,是一个标志
[root@oldboy35-edu ~]# sed -n 's#oldboy#NB#p' person.txt
101,NB,CEO
执行命令标志:e
执行命令标志e,可以将模式空间中的任何内容当做shell命令执行,并把命令执行的结果返回到模式空间。
[root@oldboy35-edu ~]# cat file.txt
/etc/passwd
/etc/my.cnf
[root@oldboy35-edu ~]# sed 's#^#ls -lh #e' file.txt
-rw-r--r--. 1 root root 2.2K Apr 10 09:14 /etc/passwd
-rw-r--r--. 1 root root 251 May 11 2016 /etc/my.cnf
创建一个测试文本,注意ls –lh 后面要有一个空格,就能够执行命令
[root@oldboy35-edu ~]# sed 's#^#ls -lh #p' file.txt
ls -lh /etc/passwd
ls -lh /etc/passwd
ls -lh /etc/my.cnf
ls -lh /etc/my.cnf
6.特殊符号=获取行号
如何获取一个文件的行号?
[root@oldboy35-edu ~]# sed "=" person.txt
1
101,oldboy,CEO
2
102,MB,CTO
3
103,Alex,COO
4
104,yy,CFO
5
105,feixue,CIO
用cat –n或nl或less –N都能查看文件的行号。
命令说明:使用特殊符号“=”就可以读取文件的行号,这是特殊用法,记住即可;行号和行不在一行。
[root@oldboy35-edu ~]# sed '1,3=' person.txt
1
101,oldboy,CEO
2
102,MB,CTO
3
103,Alex,COO
104,yy,CFO
105,feixue,CIO
读取第1~3行包含第3行的行号
改进方法:
[root@oldboy35-edu ~]# sed '=' person.txt |sed 'N;s#\n# #'
1 101,oldboy,CEO
2 102,MB,CTO
3 103,Alex,COO
4 104,yy,CFO
5 105,feixue,CIO
命令说明:sed命令N读取下一行数据并附加到模式空间。
7.一条sed语句执行多条命令
面试题:用一条sed语句实现删除文件的第三行到末尾的数据,并把剩余喊得数字10替换为01.
使用选项-e,每个-e选项后可接一个命令。
[root@oldboy35-edu ~]# sed -e '3,$d' -e 's#10#01#' person.txt
011,oldboy,CEO
012,MB,CTO
命令说明:第一个-e选项后接‘3,$d’表示删除文件的第3行到末尾的数据,第二个-e选项后接‘s#10#01#表示把数字10换成01.
[root@oldboyedu-35 ~]# sed '3a 123;4a 456' person.txt在第3行行为插入123;4a 456
101,oldboy,CEO
102,zhangyao,CTO
103,Alex,COO
123;4a 456
104,yy,CFO
105,feixue,CIO
[root@oldboyedu-35 ~]# sed '3d;4a 456' person.txt删除第3行,在第四行行为插入456
101,oldboy,CEO
102,zhangyao,CTO
104,yy,CFO
456
105,feixue,CIO
企业案例6:一个文件100行,把5,35,70行单独拿出来
[root@oldboy35-edu ~]# sed -n '5p;35p;70p' /etc/services
# IANA services version: last updated 2009-11-10
qotd 17/tcp quote
whois++ 63/udp
命令说明:这里用分号隔开即可全部显示出来。
8.保持空间和模式空间
模式空间操作命令n
命令n的作用:清空当前模式空间的内容,然后从输入文件中读取下一行。如果在命令执行过程中遇到n,那么它会改变正常的执行流程(读取数据、执行命令、打印输出、重复循环)。
Sed调试工具sedsed:sedsed软件是一个很棒的调试sed语句的工具,sedsed软件会详细显示sed执行流程。sedsed软件是时下最流行的语言python写的,简单易用。sedsed软件最新版本是1.0版本,这个版本支持所有安装python2版本的系统平台,软件官网:http://aurelio.net/projects/sedsed/.
sedsed语法:sedsed取代sed软件的位置。
常用选项:
选项 |
解释说明 |
-d |
开启调试模式 |
--hide |
隐藏一些调试信息,选项有:PATT,HOLD,COMM。 PATT是pattern模式的缩写,即模式空间 HOLD是保持空间 COMM是command的缩写,即sed命令 |
-n |
取消默认输出 |
$ |
正则里表示文件的结尾。如果在文件的开头是$,则表示空行。 |
[root@oldboy35-edu ~]# sedsed -d -n --hide=HOLD 'p;n' person.t1t
PATT:101,oldboy,CEO$
COMM:p
101,oldboy,CEO
PATT:101,oldboy,CEO$
COMM:n
PATT:102,MB,CTO$
PATT:103,alex,COO$
COMM:p
103,alex,COO
PATT:103,alex,COO$
COMM:n
PATT:104,yy,CFO$
PATT:105,feixue,CIO$
COMM:p
105,feixue,CIO
PATT:105,feixue,CIO$
COMM:n
[root@oldboy35-edu ~]# sedsed -d -n --hide=HOLD 'p;n;p' person.t1t
PATT:101,oldboy,CEO$
COMM:p
101,oldboy,CEO
PATT:101,oldboy,CEO$
COMM:n
PATT:102,MB,CTO$
COMM:p
102,MB,CTO
PATT:102,MB,CTO$
PATT:103,alex,COO$
COMM:p
103,alex,COO
PATT:103,alex,COO$
COMM:n
PATT:104,yy,CFO$
COMM:p
104,yy,CFO
PATT:104,yy,CFO$
PATT:105,feixue,CIO$
COMM:p
105,feixue,CIO
PATT:105,feixue,CIO$
COMM:n
命令N的作用:不会清空模式空间内容,并且从输入文件中读取下一行数据,追加到模式空间中,两行数据以换行符\n链接。
[root@oldboy35-edu ~]# sed '=' person.txt|sed "N;s#\n# #g"
1 101,oldboy,CEO
2 102,MB,CTO
3 103,Alex,COO
4 104,yy,CFO
5 105,feixue,CIO
sed '=' person.txt|sedsed --hide=HOLD -d 'N;s#\n# #'
第3章 awk的用法
3.1 awk在shell中使用场景
3.1.1 awk计算场景
[root@wangyoukun scripts]# vim awk.sh
#!/bin/bash
num1=$1
num2=$2
awk -va=$num1 -vb=$num2 'BEGIN{print a+b}'
awk -va=$num1 -vb=$num2 'BEGIN{print a-b}'
awk -va=$num1 -vb=$num2 'BEGIN{print a*b}'
awk -va=$num1 -vb=$num2 'BEGIN{print a/b}'
3.1.2 awk替换场景
[root@wangyoukun oldboy]# awk '$2~/Xiaoyu/{gsub(/:/,"$",$NF);print}' reg.txt
Zhang Xiaoyu 390320151 $155$90$201 ##显示Xiaoyu的捐款.每个值时都有以$开头.如$520$200$135
gsub(//,"",$NF)
gsub(/你要找的内容/,"替换成什么",在哪里列里面进行替换)
[root@oldboyedu45-lnb oldboy]# awk '{gsub(/:/,"$",$NF)}' reg.txt
3.1.3 awk取行场景
[root@wangyoukun test]# awk 'NR==1,NR==3' /etc/services
# /etc/services:
# $Id: services,v 1.48 2009/11/11 14:32:31 ovasik Exp $
#
[root@wangyoukun test]# awk 'NR==1,NR==3{print $0}' /etc/services
# /etc/services:
# $Id: services,v 1.48 2009/11/11 14:32:31 ovasik Exp $
#
3.1.4 awk取列场景
[root@wangyoukun test]# ls -lrt |awk '{print $NF}'
3.1.5 awk查找场景
[root@wangyoukun Get_Max_value]# cat get_max.sh
#!/bin/bash
get_max(){
A=
B=
while read line
do
B=$line
C=$(awk -v a=$A -v b=$B 'BEGIN{print(a>b)?"0":"1"}')
if [ $C -eq 1 ];then
A=$B
fi
done <./a.txt
echo 'Max:'$A
}
get_min(){
A=1
B=
while read line
do
B=$line
C=$(awk -v a=$A -v b=$B 'BEGIN{print(a>b)?"0":"1"}')
if [ $C -eq 0 ];then
A=$B
fi
done <./a.txt
echo 'Min:'$A
}
main(){
get_max
#sleep 5
get_min
}
main $@
3.1.6 统计行号
awk '{print NR, $0}' passwd.txt ###显示行号
3.1.7 awk统计场景
3.1.7.1 统计次数场景
[root@wangyoukun test]# awk '{i++}END{print i}' /etc/services
10774
[root@wangyoukun test]# awk '{i=i+1}END{print i}' /etc/services
10774
[root@wangyoukun test]# wc -l /etc/services
10774 /etc/services
3.1.7.2 分类统计总和场景
- 统计总和场景(单场景情况)
[root@wangyoukun ~]# awk '{sum=sum+$10}END{print sum}' access.log
2478496663
- 分类统计总和场景(多场合情况) 结合数组实现
[root@wangyoukun oldboy]# cat html.txt|awk -F "[./]+" '{h[$2]++}END{for(pol in h)print pol,h[pol]}'
www 3 ##分类统计 www post mp3 ......出现的次数
mp3 1
post 2
3.1.8 BEGIN和END模块
[root@wangyoukun Get_Max_value]# seq 10 |awk 'BEGIN{print "start"}{print $0}END{print "end"}'
start
1
2
3
4
5
6
7
8
9
10
end
3.2 awk主要可以干什么
1.取列 取行 计算 统计 查找 变量
2.统计
3.3 awk结构
awk -F "[ :]+" 'NR==2{print $4}'
awk 参数 '模式{动作}'
[root@wangyoukun ~]# ifconfig eth0
eth0 Link encap:Ethernet HWaddr 00:0C:29:00:16:B4
inet addr:10.0.0.200 Bcast:10.0.0.255 Mask:255.255.255.0
inet6 addr: fe80::20c:29ff:fe00:16b4/64 Scope:Link
UP BROADCAST RUNNING MULTICAST MTU:1500 Metric:1
RX packets:58949 errors:0 dropped:0 overruns:0 frame:0
TX packets:80971 errors:0 dropped:0 overruns:0 carrier:0
collisions:0 txqueuelen:1000
RX bytes:11036576 (10.5 MiB) TX bytes:80575920 (76.8 MiB)
[root@wangyoukun ~]# ifconfig eth0|awk -F "[ :]+" 'NR==2{print $4}'
10.0.0.200
3.4 awk的执行过程
行 列
awk –F ":"=======> awk -vFS=":"
awk -F ":" '{print $1","$3}' passwd.txt
awk -vFS=":" '{print $1,$3}' passwd.txt
[root@wangyoukun ~]# cat passwd.txt |awk -vFS=":" '{print $1","$3}'
root,0
bin,1
daemon,2
adm,3
lp,4
sync,5
shutdown,6
halt,7
mail,8
awk -F: -vOFS=":" =====> awk -vFs: -vOFS=":"
[root@wangyoukun ~]# cat passwd.txt|awk -F: -vOFS=":" '{print $NF,$2,$3,$4,$5,$6,$1}'
/bin/bash:x:0:0:root:/root:root
/sbin/nologin:x:1:1:bin:/bin:bin
/sbin/nologin:x:2:2:daemon:/sbin:daemon
/sbin/nologin:x:3:4:adm:/var/adm:adm
/sbin/nologin:x:4:7:lp:/var/spool/lpd:lp
/bin/sync:x:5:0:sync:/sbin:sync
/sbin/shutdown:x:6:0:shutdown:/sbin:shutdown
/sbin/halt:x:7:0:halt:/sbin:halt
/sbin/nologin:x:8:12:mail:/var/spool/mail:mail
[root@wangyoukun ~]# cat passwd.txt|awk -F: -vOFS=":" '{tmp=$1;$1=$NF;$NF=tmp;print}'
/bin/bash:x:0:0:root:/root:root ###条件tmp 是空杯,$1 是可乐,$NF 是雪碧
/sbin/nologin:x:1:1:bin:/bin:bin ###问题:如何调换可乐与雪碧的杯子?
/sbin/nologin:x:2:2:daemon:/sbin:daemon ###解答:有一个空杯,可以实现互换液体
/sbin/nologin:x:3:4:adm:/var/adm:adm ###过程:把可乐放进空杯,再将雪碧放进盛放可乐的空杯
/sbin/nologin:x:4:7:lp:/var/spool/lpd:lp ###子中,最后把盛放可乐的杯子放进盛放雪碧的杯子
/bin/sync:x:5:0:sync:/sbin:sync
/sbin/shutdown:x:6:0:shutdown:/sbin:shutdown
/sbin/halt:x:7:0:halt:/sbin:halt
/sbin/nologin:x:8:12:mail:/var/spool/mail:mail
3.5 通过awk找到你要的内容-模式
正则表达式作为模式
比较表达式作为模式 NR>10
范围模式
特殊模式BEGIN和END
3.5.1 正则表达式作为模式
#第3列 包含 数字3-5的行显示出来
[root@wangyoukun ~]# cat passwd.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
[root@wangyoukun ~]# awk -F":" '$3~/[3-5]/' passwd.txt #第3列 包含 数字3-5的行显示出来
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
#第5列 包含 字母的行显示出来
[root@oldboyedu45-lnb oldboy]# awk -F: '$5~/[a-z]/' passwd.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
创建环境
cat >>/oldboy/reg.txt<<EOF
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
EOF
姓氏是Zhang的人,显示他的第二次捐款金额及她的名字
[root@wangyoukun oldboy]# cat 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
[root@wangyoukun oldboy]# awk -F "[ :]+" '$1~/Zhang/{print $5,$1,$2}' reg.txt
100 Zhang Dandan ##姓氏是Zhang的人,显示他的第二次捐款金额及她的名字
90 Zhang Xiaoyu ##第二次捐款是$5
[root@oldboyedu45-lnb oldboy]# awk -F "[ :]+" '$1~/Zhang/{print $1,$2,$(NF-1)}' reg.txt
Zhang Dandan 100 ##姓氏是Zhang的人,显示他的第二次捐款金额及她的名字
Zhang Xiaoyu 90 ##第二次捐款是最后一列的前一列,记住括号要括起来
[root@oldboyedu45-lnb oldboy]# awk '$1~/Zhang/' reg.txt ##姓氏是Zhang的行
Zhang Dandan 41117397 :250:100:175
Zhang Xiaoyu 390320151 :155:90:201
awk 取第一行 NR==1 ==> NR==1{print $0} ==> NR==1{print }
[root@oldboyedu45-lnb oldboy]# awk 'NR==1' reg.txt
Zhang Dandan 41117397 :250:100:175
[root@oldboyedu45-lnb oldboy]# awk 'NR==1{print $0}' reg.txt
Zhang Dandan 41117397 :250:100:175
[root@oldboyedu45-lnb oldboy]# awk 'NR==1{print }' reg.txt
Zhang Dandan 41117397 :250:100:175
显示所有ID号码最后一位数字是1或5的人的全名
[root@oldboyedu45-lnb oldboy]# awk '$3~/[15]$/' reg.txt
Zhang Xiaoyu 390320151 :155:90:201 ##显示所有ID号码最后一位数字是1或5的人的行
Wu Waiwai 70271111 :250:80:75
Wang Xiaoai 3515064655 :50:95:135
Li Youjiu 918391635 :175:75:300
Lao Nanhai 918391635 :250:100:175
[root@oldboyedu45-lnb oldboy]# awk '$3~/[15]$/{print $1,$2}' reg.txt
Zhang Xiaoyu ##显示所有ID号码最后一位数字是1或5的人的全名
Wu Waiwai
Wang Xiaoai
Li Youjiu
Lao Nanhai
[root@wangyoukun oldboy]# awk '$2~/Xiaoyu/{gsub(/:/,"$",$NF);print}' reg.txt
Zhang Xiaoyu 390320151 $155$90$201 ##显示Xiaoyu的捐款.每个值时都有以$开头.如$520$200$135
3.6 awk 替换
gsub(//,"",$NF)
gsub(/你要找的内容/,"替换成什么",在哪里列里面进行替换)
[root@oldboyedu45-lnb oldboy]# awk '{gsub(/:/,"$",$NF)}' reg.txt
[root@oldboyedu45-lnb oldboy]# awk '{gsub(/:/,"$",$NF); print}' 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
显示所有人的全名,以姓,名的格式显示,如Meng,Feixue
[root@oldboyedu45-lnb oldboy]# awk -vOFS=, '{print $1,$2}' reg.txt
Zhang,Dandan
Zhang,Xiaoyu
Meng,Feixue
Wu,Waiwai
Liu,Bingbing
Wang,Xiaoai
Zi,Gege
Li,Youjiu
Lao,Nanhai
101.226.61.184 - - [22/Nov/2015:11:02:00 +0800] "GET /mobile/theme/oldboy/common/images/arrow-down2.png HTTP/1.1" 200 24662 "http://m.oldboyedu.com.cn/mobile/theme/oldboy/home/index.html" "Mozilla/5.0 (Linux; U; Android 5.1.1; zh-cn; HUAWEI CRR-UL00 Build/HUAWEICRR-UL00) AppleWebKit/533.1 (KHTML, like Gecko)Version/4.0 MQQBrowser/5.4 TBS/025478 Mobile Safari/533.1 MicroMessenger/6.3.7.51_rbb7fa12.660 NetType/3gnet Language/zh_CN"
3.7 企业案例 :统计/etc/services文件里面的空行数量
#i=i+1 ===> i++ 计算总次数
[root@oldboyedu45-lnb oldboy]# awk '/^$/{i++}END{print i}' /etc/services
16 ##统计/etc/services文件里面的空行数量
[root@oldboyedu45-lnb oldboy]# awk '/^$/{i=i+1 }END{print i}' /etc/services
16
[root@wangyoukun oldboy]# seq 10|awk '{i=i+$1}END{print i}'
55 ##计算从1加到10的结果
# 计算access.log中 一共使用了多少流量?
sum+=$10 ====> sum=sum+$10
[root@wangyoukun ~]# awk '{sum=sum+$10}END{print sum}' access.log
2478496663 ##计算access.log中 一共使用了多少流量?
[root@wangyoukun ~]# awk '{sum=sum+$10}END{print sum/1024^3}' access.log
2.30828 ##计算access.log中 一共使用了多少流量?没有加单位
[root@wangyoukun ~]# awk '{sum=sum+$10}END{print sum/1024^3"G"}' access.log
2.30828G ##计算access.log中 一共使用了多少流量?单位是G
3.8 小结 awk
1.BEGIN{} END{}√
2.awk统计-核心:先计算然后END{}显示结果
3.
i=i+1 === i++ 计算总次数
i=i+$xx === i+=$xxx 计算总和
[root@wangyoukun ~]# awk '{print NR, $0}' passwd.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
3.9 awk数组
处理以下文件内容,将域名取出并根据域名进行计数排序处理:(百度和sohu面试题)
http://www.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
分类统计 www post mp3 ......出现的次数
[root@wangyoukun oldboy]# cat html.txt|awk -F "[./]+" '{h[$2]++}END{for(pol in h)print pol,h[pol]}'
www 3 ##分类统计 www post mp3 ......出现的次数
mp3 1
post 2 #####套用公式比较方便
[root@oldboyedu45-lnb oldboy]# awk -F "[./]+" '$2~/www/{a++}$2~/post/{b++}$2~/mp3/{c++}END{print a,b,c}' url.txt ###这种情况只适合于小文件,种类较少的情况,不便于查看
3 2 1 ###不建议用这种方法,那么数组就产生了
[root@oldboyedu45-lnb oldboy]# awk 'BEGIN{h[110]="taotao";print h[110]}'
taotao
[root@oldboyedu45-lnb oldboy]# awk -F "[/.]+" '{h[$2]++;print "www",h["www"]}' url.txt
www 1
www 2
www 2
www 2
www 3
www 3
h[$2]++
[root@oldboyedu45-lnb oldboy]# awk -F "[/.]+" '{h[$2]++}END{print h["www"],h["mp3"],h["post"]}' url.txt
3 1 2
[root@oldboyedu45-lnb oldboy]# awk -F "[/.]+" '{h[$2]++}END{for(pol in h) print pol }' url.txt
www
mp3
post
[root@oldboyedu45-lnb oldboy]# awk -F "[/.]+" '{h[$2]++}END{for(pol in h) print pol,h[pol] }' url.txt
www 3
mp3 1
post 2
'{h[$2]++}END{for(pol in h) print pol h[pol] }'
变量 数组 元素名称,内容
房间号码
统计access.log中每个ip的访问次数
awk '{h[$1]++}END{for(pol in h) print pol,h[pol]}' access.log |sort -rnk2|head
[root@wangyoukun ~]# awk '{h[$1]++}END{for(pol in h) print pol,h[pol]}' access.log |head |sort -rnk2
101.226.125.119 569
180.154.137.177 516
101.226.125.118 437
180.158.118.17 347
101.226.125.115 284
14.152.68.38 162
140.206.89.150 130
101.226.125.116 127
117.12.191.55 106
110.75.248.79 1
3.10 awk 数组知识小结
3.10.1 特殊的模式BEGIN{} END{}
BEGIN{} 模块在awk读取文件之前就执行
awk 'BEGIN{print "start"} {print}' reg.txt
[root@wangyoukun oldboy]# awk 'BEGIN{print "start"} {print }' reg.txt
start
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
1)测试
2) 定义或修改awk内置变量
-vOFS=: =====> 'BEGIN{OFS=:}'
END{}在awk读取完所有的文件的时候,再执行END模块,一般用来输出一个结果(累加,数组结果),
先计算,END{}显示最终结果
3.10.2 数组活学活用
awk -F "[/.]+" '{h[$2]++}END{for(pol in h) print pol,h[pol] }' url.txt
拿好菜刀(分隔符),找到要统计的列,计算结果
3.10.3 计算总次数 i=i+1 === i++
awk '/^$/{i++}END{print i}' /etc/services
##统计/etc/services文件里面的空行数量
3.10.4 计算总和 i=i+$xx === i+=$xxx
awk '{sum=sum+$10}END{print sum}' access.log
seq 10|awk '{i=i+$1}END{print i}'
3.11 练习题目
3.11.1 题目一(已解答)
#第1列 ip地址
#第7列 URL 网址
#第10列 文件的大小 流量大小
显示access.log中第7列中以.jpg或.png结尾的ip地址和URL
解答:awk '$7~/(.jpg)|(.png)$/{print $1,$7}' access.log
显示access.log中第10列中大于5000的ip地址和url
解答:awk '$10>5000{print $1,$7}' access.log
3.12 题目二 尚在研究中…...
1.分析谁在破解你的密码(每个ip破解的次数) secure-2016xxxx
2.分析每个用户被破解的次数
3.access.log 计算每个ip地址使用的流量
4.统计access.log显示每个ip地址的访问次数和每个ip地址使用的流量
第4章 用法举例
4.1 awk基础用法举例
[root@wangyoukun AWK_SED_GREP]# cat html.txt |awk -F '[:/]' 'BEGIN{print "start"}{h[$4]++}END{for(i in h)print h[i],i}'
start
1 mp3.etiantian.org
2 post.etiantian.org
3 www.etiantian.org
4.2 access访问日志 实战用法举例一
注释项:
#第1列 ip地址
#第7列 URL 网址
#第10列 文件的大小 流量大小
4.2.1 显示access.log中第7列中以.jpg或.png结尾的ip地址和URL
解答:awk '$7~/(.jpg)|(.png)$/{print $1,$7}' access.log
cat access.log |awk '$7~/.jpg$|.png$/{h[$1]++}END{for(a in h)print h[a],a,$7}'|sort -gr
[root@wangyoukun use_awk_2]# cat access.log |awk '$7~/.jpg$|.png$/{h[$1]++}END{for(a in h)print h[a],a,$7}'|sort -gr|head
778 114.83.184.139 /online/oldboyonline/images/forms/validatePass.png
732 112.64.171.98 /online/oldboyonline/images/forms/validatePass.png
722 58.220.223.62 /online/oldboyonline/images/forms/validatePass.png
573 117.136.66.10 /online/oldboyonline/images/forms/validatePass.png
446 116.216.30.47 /online/oldboyonline/images/forms/validatePass.png
383 223.104.5.197 /online/oldboyonline/images/forms/validatePass.png
383 116.216.0.60 /online/oldboyonline/images/forms/validatePass.png
301 223.104.5.202 /online/oldboyonline/images/forms/validatePass.png
289 114.111.166.22 /online/oldboyonline/images/forms/validatePass.png
269 114.141.164.180 /online/oldboyonline/images/forms/validatePass.png
4.2.2 显示access.log中第10列中大于5000的ip地址和url
解答:awk '$10>5000{print $1,$7}' access.log
cat access.log|awk '$10>5000{h[$1]++}{for(a in h)print h[a],a,$7}' |sort -gr
4.2.3 access.log 计算每个ip地址使用的流量
cat access.log |awk '{h[$1]+=$10}END{for(a in h)print h[a],a}'|sort -gr |head
31362956 114.83.184.139
22431302 117.136.66.10
21466000 116.216.30.47
21464856 223.104.5.197
19145329 116.216.0.60
17219553 114.141.164.180
17121524 114.111.166.22
16911512 223.104.5.202
15969887 116.228.21.187
15255013 112.64.171.98
4.2.4 统计access.log显示每个ip地址的访问次数和每个ip地址使用的流量
每个ip地址访问次数
cat access.log |awk '{h[$1]++}END{for(a in h)print h[a],a}'|sort -gr |head
每个ip地址使用的流量
cat access.log |awk '{h[$1]+=$10}END{for(a in h)print h[a],a}'|sort -gr |head
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】凌霞软件回馈社区,博客园 & 1Panel & Halo 联合会员上线
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】博客园社区专享云产品让利特惠,阿里云新客6.5折上折
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步