1. 三剑客简介linux
2. sed命令详解面试
3. awk命令详解正则表达式
在 Shell 下使用这些正则表达式处理文本最多的命令有下面几个工具:shell
| 命令 | 描述 | | grep | 默认不支持扩展表达式,加-E 选项开启 ERE。若是不加-E 使用花括号要加转义符\{\} | | egrep | 支持基础和扩展表达式 | | awk | 支持 egrep 全部的正则表达式 | | sed | 默认不支持扩展表达式,加-r 选项开启 ERE。若是不加-r 使用花括号要加转义符\{\} |
咱们都知道,在Linux中一切皆文件,好比配置文件,日志文件,启动文件等等。若是咱们相对这些文件进行一些编辑查询等操做时,咱们可能会想到一些vi,vim,cat,more等命令。可是这些命令效率不高,而在linux中有三种工具:顶配awk,中配sed,标配grep。使用这些工具,咱们可以在达到一样效果的前提下节省大量的重复性工做,提升效率。编程
编辑文件也是这样,之前咱们修改一个配置文件,须要移动光标到某一行,而后添加点文字,而后又移动光标到另外一行,注释点东西…….可能修改一个配置文件下来须要花费数十分钟,还有可能改错了配置文件,又得返工。这仍是一个配置文件,若是数十个数百个呢?所以当你学会了sed命令,你会发现利用它处理文件中的一系列修改是颇有用的。只要想到在大约100多个文件中,处理20个不一样的编辑操做能够在几分钟以内完成,你就会知道sed的强大了。vim
sed [选项] [sed命令] [输入文件]数组
说明:缓存
1,注意sed软件以及后面选项,sed命令和输入文件,每一个元素之间都至少有一个空格。bash
2,sed -commands(sed命令)是sed软件内置的一些命令选项,为了和前面的options(选项)区分,故称为sed命令app
3,sed -commands 既能够是单个sed命令,也能够是多个sed命令组合。
4,input -file (输入文件)是可选项,sed还可以从标准输入如管道获取输入。
sed读取一行,首先将这行放入到缓存中
而后,才对这行进行处理
处理完成之后,将缓冲区的内容发送到终端
存储sed读取到的内容的缓存区空间称之为:模式空间(Pattern Space)
option[选项] | 解释说明(带*的为重点) |
---|---|
-n (no) | 取消默认的sed软件的输出,常与sed命令的p连用。* |
-e (entry) | 一行命令语句能够执行多条sed命令 * |
-r (ruguler) | 使用扩展正则表达式,默认状况sed只识别基本正则表达式 * |
-i (inside) | 直接修改文件内容,而不是输出到终端,若是不使用-i选项sed软件只是修改在内存中的数据,并不会影响磁盘上的文件* |
sed -commands[sed命令] | 解释说明(带*的为重点) |
---|---|
a (append) | 追加,在指定行后添加一行或多行文本 * |
c (change) | 取代指定的行 |
d (delete) | 删除指定的行 * ` |
i (insert) | 插入,在指定行前添加一行或多行文本 * |
p (print) | 打印模式空间内容,一般p会与选项-n一块儿使用* |
特殊符号 | 解释说明(带*的为重点) |
---|---|
! | 对指定行之外的全部行应用命令* |
这里咱们须要用到2个sed命令,分别是:
实例1:a
[root@ken ~]# sed "2a 这是新添加的一行" test this is the first line this is the second line 这是新添加的一行 this is the third line this is the forth line this is the fivth line this is the sixth line this is the seventh line this is the eighth line this is the ninth line this is the tenth line
实例2:i
[root@ken ~]# sed "2i 我又新添加了一行" test this is the first line 我又新添加了一行 this is the second line this is the third line this is the forth line this is the fivth line this is the sixth line this is the seventh line this is the eighth line this is the ninth line this is the tenth line
实例3:同时增长多行(/n)
[root@ken ~]# sed "2i 这是第一条记录\n这是第二条记录\n这是第三条记录" test this is the first line 这是第一条记录 这是第二条记录 这是第三条记录 this is the second line this is the third line this is the forth line this is the fivth line this is the sixth line this is the seventh line this is the eighth line this is the ninth line this is the tenth line
实例1:删除全部的行
[root@ken ~]# cp test{,.bak} [root@ken ~]# sed 'd' test
命令说明:若是在sed命令前面不指定地址范围,那么默认会匹配全部行,而后使用d命令删除功能就会删除这个文件的全部内容
实例2:删除指定的行
[root@ken ~]# cat test.bak >test [root@ken ~]# sed '2d' test this is the first line this is the third line this is the forth line this is the fivth line this is the sixth line this is the seventh line this is the eighth line this is the ninth line this is the tenth line
实例3:删除指定范围行
[root@ken ~]# sed '2,5d' test this is the first line this is the sixth line this is the seventh line this is the eighth line this is the ninth line this is the tenth line
实例4:删除匹配的行
[root@ken ~]# sed '/sixth/d' test this is the first line this is the second line this is the third line this is the forth line this is the fivth line this is the seventh line this is the eighth line this is the ninth line this is the tenth line
命令说明:在sed软件中,使用正则的格式和awk同样,使用2个”/“包含指定的正则表达式,即“/正则表达式/”。
实例5:删除指定行到行尾的内容
[root@ken ~]# sed '2,$d' test this is the first line
第二行也会被删掉
实例6:取反
1、
[root@ken ~]# sed '2,3!d' test this is the second line this is the third line
2、
[root@ken ~]# sed '/tenth/!d' test this is the tenth line
[root@ken ~]# sed '2c 改过以后的第二行' test this is the first line 改过以后的第二行 this is the third line this is the forth line this is the fivth line this is the sixth line this is the seventh line this is the eighth line this is the ninth line this is the tenth line this is sixth line
sed -i ‘s/目标内容/替换内容/g’ ken.log
sed -i ‘s#目标内容#替换内容#g’
实例1:
[root@ken ~]# sed 's/line/hang/g' test this is the first hang this is the second hang this is the third hang this is the forth hang this is the fivth hang this is the sixth hang this is the seventh hang this is the eighth hang this is the ninth hang this is the tenth hang this is sixth hang
命令说明:从上面命令的结果咱们就知道sed命令默认不会修改文件的内容
实例2:
[root@ken ~]# sed -i 's/line/hang/g' test [root@ken ~]# cat test this is the first hang this is the second hang this is the third hang this is the forth hang this is the fivth hang this is the sixth hang this is the seventh hang this is the eighth hang this is the ninth hang this is the tenth hang this is sixth hang
命令说明:若是想真正的修改文件内容,咱们就须要使用选项“-i”,这个要和sed命令“i”区分开来。同时咱们能够发现命令执行后的结果是没有任何输出的。
实例1:
[root@ken ~]# sed '2p' test this is the first hang this is the second hang this is the second hang this is the third hang this is the forth hang this is the fivth hang this is the sixth hang this is the seventh hang this is the eighth hang this is the ninth hang this is the tenth hang this is sixth hang [root@ken ~]# sed -n '2p' test this is the second hang
实例2:
[root@ken ~]# sed -n '2,5p' test this is the second hang this is the third hang this is the forth hang this is the fivth hang
实例3:
[root@ken ~]# sed -n '/ninth/p' test this is the ninth hang
实例1:
[root@ken ~]# sed -e '2d' -e '5d' test this is the first hang this is the third hang this is the forth hang this is the sixth hang this is the seventh hang this is the eighth hang this is the ninth hang this is the tenth hang this is sixth hang
实例2:
[root@ken ~]# sed -n -e '2p' -e '5p' test this is the second hang this is the fivth hang
第一种方法: [root@ken ~]# cp test{,.bak} [root@ken ~]# ls anaconda-ks.cfg a.out ken1 test test1 test2 test.bak test.txt [root@ken ~]# grep -v -E “(^$)|(^#)” test.bak root:x:0:0:root:/root:/bin/bash bin:x:1:1:bin:/bin:/sbin/nologin daemon:x:2:2:daemon:/sbin:/sbin/nologin i#adm:x:3:4:adm:/var/adm:/sbin/nologin lp:x:4:7:lp:/var/spool/lpd:/sbin/nologin 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@ken ~]# grep -v -E “(^$)|(^#)” test.bak > test [root@ken ~]# 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 i#adm:x:3:4:adm:/var/adm:/sbin/nologin lp:x:4:7:lp:/var/spool/lpd:/sbin/nologin 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@ken ~]# sed -i -e ‘/^$/d’ -e ‘/^#/d’ test.bak [root@ken ~]# cat test.bak root:x:0:0:root:/root:/bin/bash bin:x:1:1:bin:/bin:/sbin/nologin daemon:x:2:2:daemon:/sbin:/sbin/nologin i#adm:x:3:4:adm:/var/adm:/sbin/nologin lp:x:4:7:lp:/var/spool/lpd:/sbin/nologin 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
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
7)取反操做
显示非1-3行
# sed -n ‘1,3!p’ passwd
awk不只仅时linux系统中的一个命令,并且是一种编程语言,能够用来处理数据和生成报告(excel)。处理的数据能够是一个或多个文件,能够是来自标准输入,也能够经过管道获取标准输入,awk能够在命令行上直接编辑命令进行操做,也能够编写成awk程序来进行更为复杂的运用。
awk处理的内容能够来自标准输入(<),一个或多个文本文件或管道。
读取文本第一行,首先会和匹配模式进行相匹配,若是发现第一行内容不和模式相匹配的话,就继续读取下一行
读取到第二行发现和模式相匹配,就会执行花括号里面的动做
而后继续读取下一行,发现和模式相匹配,就会执行花括号里面的动做
...
依次读取全文
-F:指定分隔符
记录(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:记录分隔符
$1 $2 … $n 输出一个指定的字段 $NF 输出最后一个字段 $0 输出整条记录
[root@ken ~]# 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)
准备测试文件
[root@ken ~]# head /etc/passwd > test [root@ken ~]# 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
实例1:打印行号
[root@ken ~]# awk '{print NR,$0}' test 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 operator:x:11:0:operator:/root:/sbin/nologin
实例2:输出有多余5个字段的行的第三个字段
[root@ken ~]# awk -F ':' 'NF>=5{print $3}' test 0 1 2 3 4 5 6 7 8 11
实例3:输出每行行号和该行有几个字段
[root@ken ~]# awk -F ':' '{print NR,NF}' test 1 7 2 7 3 7 4 7 5 7 6 7 7 7 8 7 9 7 10 7
例子4:打印出来用户名以及对应的shell类型
[root@ken ~]# awk -F “:” ‘{print $1,$NF}’ test root /bin/bash bin /sbin/nologin daemon /sbin/nologin i#adm /sbin/nologin lp /sbin/nologin shutdown /sbin/shutdown halt /sbin/halt mail /sbin/nologin operator /sbin/nologin [root@ken ~]# awk -F “:” ‘{print $1,$7}’ test root /bin/bash bin /sbin/nologin daemon /sbin/nologin i#adm /sbin/nologin lp /sbin/nologin shutdown /sbin/shutdown halt /sbin/halt mail /sbin/nologin operator /sbin/nologin
实例1:匹配整行
[root@ken ~]# awk '/^root/' test root:x:0:0:root:/root:/bin/bash
和下面的效果是同样的
[root@ken ~]# awk '$0~/^root/' test root:x:0:0:root:/root:/bin/bash
注意:awk只用正则表达式的时候是默认匹配整行的即‘$0~/^root/’和‘/^root/’是同样的。
实例2:匹配一行中的某一列
[root@ken ~]# awk -F ':' '$5~/root/' test root:x:0:0:root:/root:/bin/bash
提示:
$5~/root/表示第五个区域(列)匹配正则表达式/root/,既第5列包含root这个字符串,则显示这一行。
实例3:匹配行尾为sync
[root@ken ~]# awk -F ':' '/sync$/{print $0}' test sync:x:5:0:sync:/sbin:/bin/sync
实例4:显示名字和登陆类型
[root@ken ~]# awk -F ':' '{print $1,$NF}' test 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 $NF:表示匹配的末尾部分,这里也能够写成$7
[root@ken ~]# ip a 1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN group default qlen 1000 link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00 inet 127.0.0.1/8 scope host lo valid_lft forever preferred_lft forever inet6 ::1/128 scope host valid_lft forever preferred_lft forever 2: eth0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc pfifo_fast state UNKNOWN group default qlen 1000 link/ether 00:0c:29:99:ea:a6 brd ff:ff:ff:ff:ff:ff inet 172.20.10.6/24 brd 172.20.10.255 scope global noprefixroute eth0 valid_lft forever preferred_lft forever inet6 2408:84f4:86:47e1:20c:29ff:fe99:eaa6/64 scope global mngtmpaddr dynamic valid_lft forever preferred_lft forever inet6 fe80::20c:29ff:fe99:eaa6/64 scope link valid_lft forever preferred_lft forever
第一种方法:
[root@ken ~]# ip a | awk -F ' +' 'NR==9{print $3}' | awk -F '/' '{print $1}' 172.20.10.6
第二种方法:
[root@ken ~]# ip a | grep -E '^ +.*inet\>.*' | awk -F ' +|/' 'NR==2{print $3}' 172.20.10.6
第三种方法:
[root@ken ~]# hostname -i | awk -F ' ' '{print $3}' 172.20.10.6
第四种方法:
[root@ken ~]# ip a | grep brd.*glo | awk -F ' +|/' '{print $3}' 172.20.10.6
第五种方法:
[root@ken ~]# ip a | grep "scope" | awk 'NR==3{print $0}' | awk -F "( |/)+" '{print $3}' 172.20.10.6
方法还有不少不少,你们若是对本身有高要求的话,要至少写出来十种以上的方法哦!
实例1:
[root@ken ~]# ifconfig eth0 | awk -F "[ :]+" 'NR==2{print $3}' 172.20.10.6 [root@ken ~]# ifconfig eth0 | awk -F "[^0-9.]+" 'NR==2{print $2}' 172.20.10.6 #上面的也能够写成 [root@ken ~]# ifconfig eth0 | awk 'BEGIN{FS="[ :]+"}NR==2{print $3}' 172.20.10.6 [root@ken ~]# ifconfig eth0 | awk 'BEGIN{FS="[^0-9.]+"}NR==2{print $2}' 172.20.10.6
实例2:在读取文件以前,输出些提示性信息(表头)。
[root@ken ~]# awk -F ':' 'BEGIN{print "username","bash type"}{print $1,$NF}' test username bash type 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
EHD在awk读取完全部的文件的时候,再执行END模块,通常用来输出一个结果(累加,数组结果),也能够是和BEGIN模块相似的结尾标识信息与BEGIN模式相对应的END模式,格式同样,可是END模式仅在awk处理完全部输入行后才进行处理。
实例1:
[root@ken ~]# awk -F ':' 'BEGIN{print "username","bash type"}{print $1,$NF}END{print "end of file"}' test username bash type 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
实例2:统计包含root的行的数量
方法一:
[root@ken ~]# cat test | grep root| wc -l 2
方法二:
[root@ken ~]# cat test | grep -c root 2
方法三:
[root@ken ~]# cat /etc/passwd | awk 'BEGIN{i=0}/root/{i++}END{print i}' 2 [root@ken ~]# cat /etc/passwd | awk '/root/{i++}END{print i}' 2
回顾一下awk的结构
awk -F 指定分隔符 ‘BRGIN{}END{}’,以下图
数组构成:
数组名[元素名]=值
如图不难发现,awk数组就和酒店同样。数组的名称就像是酒店名称,数组元素名称就像酒店房间号码,每一个数组元素里面的内容就像是酒店房间里面的人。
[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@ken ~]# cat test | awk -F '/+' '{print $2}' | sort | uniq -c 7 www.qq.com 13 www.sina.com 25 www.taobao.com</pre>
方法二:
[root@ken ~]# cat test | awk -F '/+' '{h[$2]++}END{for (i in h) print i,h[i]}' www.sina.com 13 www.qq.com 7 www.taobao.com 25
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@ken]# 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