linux三剑客及正则表达(grep,sed,awk)

首先我们现在知道Linux下一切皆文件,对Linux的操作就是对文件的处理,那么怎么能更好的处理文件呢?这就要用到我们上面的三剑客命令。

    在说这三个命令前我们要插入一个小插曲就是“正则表达式”。


目录

正则表达与三剑客的说明

grep

sed

awk

awk,for,if循环实现高级搜索



正则表达与三剑客的说明

    所谓的正则表达式我个人理解就是正规的表示方法。他是用简单的方法来实现强大的功能,所以深受计算机爱好者的使用。

    三剑客与正则表达式是什么关系呢?

  我们可以这样理解,三剑客就是普通的命令,有的把他们叫做工具,在我看来都一样。而正则表达式就好比一个模版。三剑客能读懂这个模版。就这么简单。

三剑客:

1.grep文本搜索工具(过滤匹配的行)

Linux系统中grep命令是一种强大的文本搜索工具,它能使用正则表达式搜索文本,并把匹配的行打印出来。grep全称是Global Regular Expression Print,表示全局正则表达式版本,它的使用权限是所有用户。

2.sed流式编辑器   逐行处理

对文档进行非交互式增删改查的操作

3.awk精确搜索 (二次处理)

简单来说,awk就是把文件逐行读入,以空格为默认分隔符将每行切片,然后可以对切开的部分进行各种处理。相对于grep的查找、匹配和sed的编辑,awk适合对文本进行较复杂的格式处理。

三剑客的对比:

grep:文本过滤器,如果仅仅是过滤文本,可使用grep,其效率要比其他的高很多

sed:Stream EDitor,流编辑器,默认只处理模式空间,不处理原数据,如果你处理的数据是针对行进行处理的,可以使用sed

awk:报告生成器,格式化以后显示。如果对处理的数据需要生成报告之类的信息,或者你处理的数据是按列进行处理的,最好使用awk

正则表达式是一个模版,这个模版是由一些普通字符和一些元字符组成。普通字符包括大小写的字母和数字,而元字符具有特殊的含义。具体如下

 

 

元字符 补充



grep

grep过滤工具

         ---格式:grep 【选项】 “正则表达式“ 文件

egrep 过滤工具

         ---格式:egrep 【选项】 “扩展正则表达式“ 文件

举例子:

head -5 /etc/passwd > user      //准备素材
grep ^root user    //找以root开头的行
grep bash$ user     //找以bash结尾的行
grep ^$ user   //找空行
grep -v ^$ user  //显示除了空行的内容

grep "[root]" user    //找rot任意一个字符 
grep "[rot]" user    //效果同上
grep "[^rot]" user   //显示r或o或t以外的内容
grep "[0123456789]" user   //找所有数字
grep "[0-9]" user    //效果同上
grep "[^0-9]" user   //显示数字以外内容
grep "[a-z]" user    //找所有小写字母
grep "[A-Z]" user    //找所有大写字母
grep "[a-Z]" user    //找所有字母
grep "[a-Z0-9]" user   //找所有字母和数字
grep "[^a-Z0-9]" user	 //找特殊符号

grep "." user   //找任意单个字符,文档中每个字符都可以理解为任意字符
grep "r..t" user  //找rt之间有2个任意字符的行
grep "r.t" user  //找rt之间有1个任意字符的行,没有匹配内容,就无输出
grep "*" user  //错误用法,*号是匹配前一个字符任意次,不能单独使用
grep "ro*t" user  //找rt,中间的o有没有都行,有几次都行
grep ".*" user   //找任意,包括空行 .与*的组合在正则中相当于通配符的效果

grep "ro\{1,2\}t" user    //找rt,中间的o可以有1~2个
grep "ro\{2,6\}t" user    //找rt,中间的o可以有2~6个
grep "ro\{2,\}t" user     //找rt,中间的o可以有2个以及2个以上
grep "ro\{1,\}t" user     //找rt,中间的o可以有1个以及1个以上
grep "ro\{3,\}t" user     //找rt,中间的o可以有3个以及3个以上
grep "ro\{2\}t" user      //找rt,中间的o必须只有有2个
grep "ro\{1\}t" user       //找rt,中间的o必须只有有1个  
grep "ro\{3\}t" user        //找rt,中间的o必须只有有3个

grep "\(0:\)\{2\}" user  //找连续的2个0:  小括号的作用是将字符组合为一个整体



以上命令均可以加-E选项并且去掉所有\,改成扩展正则的用法,比如
grep "ro\{1,\}t" user可以改成 grep -E "ro{1,}t" user    
或者
egrep "ro{1,}t" user   

grep "ro\{1,\}t" user    //使用基本正则找o出现1次以及1次以上
egrep "ro{1,}t" user  //使用扩展正则,效果同上,比较精简
egrep "ro+t" user   //使用扩展正则,效果同上,最精简
grep "ro\{0,1\}t" user  //使用基本正则找o出现0~1次
egrep "ro{0,1}t" user   //使用扩展正则,效果同上,比较精简
egrep "ro?t" user  //使用扩展正则,效果同上,最精简
egrep "root|^bin" user   //找有root或者以bin开头的行
#此时的egrep与grep -E相同


#单词边界
cat  aa   //素材文件,里面有一些"the"
the
there
the6
the_
123the
egrep "the\b" aa    //在aa文件中找the,右边不允许出现数字、字母、下划线
egrep "\bthe\b" aa  //找the,两边都不允许出现数字、字母、下划线

 grep正则表达式练习 

先在regular_express.txt写入内容....
1,过滤包含 the 关键字 
grep -n 'the' regular_express.txt
2,过滤不包含 the 关键字 
grep -vn 'the' regular_express.txt 
3,过滤不论大小写 the 关键字
grep -in 'the' regular_express.txt
4,过滤 test 或 taste 这两个单字
grep -n 't[ae]st' regular_express.txt
5,过滤有 oo 的字节
grep -n 'oo' regular_express.txt 
6,过滤不想要 oo 前面有 g 的
grep -n '[^g]oo' regular_express.txt 
7,过滤 oo 前面不想有小写字节
grep -n '[^a-z]oo' regular_express.txt.
8,过滤有数字的那一行 
grep -n '[0-9]' regular_express.txt 
9,过滤以 the 开头的 
grep -n '^the' regular_express.txt 
10,过滤以小写字母开头的 
grep -n '^[a-z]' regular_express.txt
11,过滤开头不是英文字母 
grep -n '^[^a-zA-Z]' regular_express.txt 
12,过滤行尾结束为小数点.那一行
grep -n '\.$' regular_express.txt 
13,过滤空白行
grep -n '^$' regular_express.txt 
14,过滤出 g??d 的字串
grep -n 'g..d' regular_express.txt 
15,过滤至少两个 o 以上的字串 
grep -n 'ooo*' regular_express.txt
16,过滤 g 开头和 g 结尾但是两个 g 之间仅存在至少一个 o
grep -n 'goo*g' regular_express.txt
17,过滤两个 o 的字串
grep -n 'o\{2\}' regular_express.txt 
18,过滤 g 后面接 2 到 5 个 o,然后在接一个 g 的字串 
grep -n 'go\{2,5\}g' regular_express.txt 
19,过滤 g 后面接 2 个以上 o 的
grep -n 'go\{2,\}g' regular_express.txt

grep "bash$" /etc/passwd | sed 's/:.*//'    //找到以bash结尾的用户
再用sed去掉用户后面:开始的所有内容,留下的就是用户名


sed

用法1:前置命令 | sed  [选项]  '条件指令'

用法2:sed  [选项]  '条件指令'  文件.. ..

选项: -n  屏蔽默认输出   -r  支持扩展正则  -i 修改源文件

指令: p  输出    d  删除    s替换     a行下追加    i行上添加    c替换整行

以下列子中的文件内容可以自己写入如
:head /etc/passwd > user

sed -n 'p' user    //输出所有行
sed -n '1p' user   //输出第1行
sed -n '2p' user   //输出第2行
sed -n '3p' user    //输出第3行
sed -n '2,4p' user   //输出2~4行
sed -n '2p;4p' user   //输出第2行与第4行
sed -n '2,+1p' user   //输出第2行以及后面1行
sed -n '/^root/p' user   //输出以root开头的行  
sed -n '/root/p' user   //输出包含root的行
sed -nr '/^root|^bin/p' user
将以上语句中的p指令改为d指令可以实现对应行的删除效果
比如sed -n '2p' user 改成 sed '2d' user  是删除第2行
sed -n '2!p' user   //输出除了第2行的内容,加!是取反效果
sed '3,+1!d' user     //删除第3行、第4行以外的行
sed -n '=' user      //显示行号,=号在sed中可以显示行号
sed -n '$=' user   //查看文档最后一行的行号,相当于查看文档总行数

sed -i '$d' user   //删除文档的最后一行并保存

sed 's/2017/6666/' test.txt   //把所有行的第1个2017替换成6666
sed 's/2017/6666/2' test.txt  //把所有行的第2个2017替换成6666
sed '1s/2017/6666/' test.txt  //把第1行的第1个2017替换成6666
sed '3s/2017/6666/3' test.txt  //把第3行的第3个2017替换成6666
sed '3s/2017//3' test.txt  //把第3行的第3个2017替换成空,相当
于删除
sed '/2024/s/2017/6666/' test.txt  //找到有2024的行,将2017替换
成6666



尝试将user文档中/bin/bash替换成/sbin/sh
sed '1s//bin/bash//sbin/sh/' user   //直接替换,报错
sed '1s/\/bin\/bash/\/sbin\/sh/' user  //使用转义符号可以
成功,但不方便
sed '1s!/bin/bash!/sbin/sh!' user  //最佳方案,更改s的替换符
sed '1s@/bin/bash@/sbin/sh@' user  //替换符号可以用所有
数字键上的

sed 's/[0-9]//g' nssw.txt
sed 's/.//2;s/.$echo abc > abc                            //创建素材
sed -r 's/(a)(b)(c)/\3\2\1/' abc  //替换abc时复制每一个字符,后面替换的内容用\数字粘贴,可以任意调换位置
echo xyz >> xyz   //追加内容
sed -r 's/(a)(b)(c)/\3\2\1/' abc  //再用之前的方法无法替换第2行
sed -r 's/(.)(.)(.)/\3\2\1/' abc  //将具体字符用 . 替代即可,然后,再将追加abcd时,上述方案失灵
sed -r 's/^(.)(.*)(.)$/\3\2\1/' abc   //再次升级,分别找到第1个字符和最后1个字符,中间可以是任意
sed -r 's/^(.)(.*)(.)$/\3\2\1/'  nssw.txt   //达成需求
//' test 

sed -r 's/([A-Z])/(\1)/g'  nssw.txt  //先找到任意大写字母,然后保留,最后替换成带括号的状态
 

sed 'a 666' user    //所有行的下面追加666
sed '1a 666' user   //第1行的下面追加666
sed '/^bin/a 666' user   //在以bin开头的行的下面追加666
sed 'i 666' user  //所有行的上面添加666
sed '5i 666' user   //第5行的上面添加666
sed '$i 666' user  //最后1行的上面添加666
sed 'c 666' user   //所有行都替换成666
sed '1c 666' user  //替换第1行为666



sed -n '/bash$/s/:.*//p' /etc/passwd  //用sed找到以bash结尾的用户
然后去掉用户后面:开始的所有内容,最后加p的作用是仅仅显示被
替换的行

awk

格式1:前置指令 | awk [选项] '[条件]{指令}' 

格式2:awk [选项] '[条件]{指令}' 文件

指令:

print 输出

选项:

-F 定义分隔符

内置变量:

$1第1列  $2第2列  $3 ... $0所有列   NR行号   NF列号 awk '{print $1}'  test.txt  //输出所有行的第1列

使用正则

  ~包含   !~不包含

使用数字或者字符串 

==  !=   >=   >   <=   <

逻辑组合 

&&并且   ||或者

运算

 /   *   %   +   - .......

awk执行额外任务

BEGIN{   }    执行1次,读取文档之前执行

        逐行任务     执行n次 ,读取文档时执行

END{   }      执行1次,读取文档之后执行

简单的例子:

awk '{print $1}'  test.txt  //输出所有行的第1列
awk '{print $3}'  test.txt  //输出所有行的第3列
awk '/the/{print $3}'  test.txt  //输出有the的行的第3列
awk '/the/{print NR}'  test.txt  //输出有the的行的行号
awk '{print NR}'  test.txt  //输出所有行的行号
awk '{print NF}'  test.txt  //输出所有行的列号
awk '{print $0,NR}'  test.txt  //输出所有列然后空格输出行号
head -5 /etc/passwd > user
awk -F: '{print $1}' user   //使用-F:修改分隔符为冒号,输出第1列
awk -F: '{print $1,$7}' user  //使用-F:修改分隔符为冒号,输出第1列空格第7列
awk -F: '{print $1,"的解释器是",$7}' user   //输出常量加引号



ifconfig eth0  | awk '/RX p/{print "服务器eth0网卡的接收流量是"$5"字节"}'
ifconfig eth0  | awk '/TX p/{print "服务器eth0网卡的发送流量是"$5"字节"}'
df -h | awk '/\/$/{print "根分区剩余容量是"$4}'


awk -F: '$6~/bin/{print}' user   //找第6列包含bin的行
awk -F: '$6!~/bin/{print}' user  //找第6列不包含bin的行




awk -F: 'NR==1{print}' user    //输出第1行
awk -F: 'NR!=3{print}' user     //输出除了第3行以外的行
awk -F: 'NR<4{print}' user     //输出1~3行
awk -F: '$1=="root"{print}' user   //输出第1列等于root的行
awk -F: '$1~/root/{print}' user   //输出第1列包含root的行


wk -F: '$3<10&&$7~/bash/' /etc/passwd   //输出第3列(UID)小于10并且
第7列包含bash的行,当给了条件输出一整行时{print}可以省略不写
awk -F: 'NR>=2&&NR<=6' /etc/passwd  //输出2~6行
awk -F: '$1~/root/||$3<=5' /etc/passwd  //输出第1列包含root或者UID小
于等于5的行



awk 'NR%2==0' user  //输出偶数行
awk  'BEGIN{   }{   }END{    }'   //使用时基本框架
awk 'BEGIN{print "xyz"}{print "xyz"}END{print "xyz"}'  user   //输出1
个xyz之后再根据user文档的行数输出5个xyz,最后再输出一个xyz

awk 'BEGIN{print "User\tUID\tHome"}' 	//输出表头信息 
awk -F: '{print $1"\t"$3"\t"$6}' user    //输出内容,用户名,uid,家目录
awk 'END{print "总计"NR"行"}' user   //最后输出行数

awk -F: 'BEGIN{print "User\tUID\tHome"}{print $1"\t"$3"\t"$6}
END{print "总计"NR"行"}'  user


awk '{print $1}' /var/log/httpd/access_log   //可以找出访问者的ip,但是效果不完美,可以用后面的数组方式解决


awk,for,if循环实现高级搜索

awk 中使用if单分支,如果满足条件,就执行指令,不满足就不执行任何指令  

if(条件){指令}

awk -F: 'BEGIN{x=0}{if($7~/bash/){x++}}END{print x}'  /etc/passwd  
#####统计系统中,有多少用户使用了bash,首先定义变量x,然后使用if判断如果每找到一行的$7包含bash,就把x+1,所有逐行任务结束后,最终使用end任务输出x的值,也就是找系统中使用bash作为解释器的用户数量

双分支,如果满足条件就执行指令,不满足就执行else后面的指令 if(条件){指令}else{指令}

awk -F: 'BEGIN{x=0;y=0}{if($7=="/bin/bash"){x++}else{y++}}END{print x,y}' /etc/passwd
//统计系统中使用bash作为解释器的用户,和没有使用bash的用户数量,使用if判断如果每找到一行的$7是/bin/bash,就把x+1,否则y+1,最后使用end输出x与y的值
 

 多分支 {if (条件){指令}else if (条件){指令}else{指令}}

awk -F: '{if($7=="/bin/bash"){x++}else
if($7=="/sbin/nologin"){y++}else{z++}}END{print x,y,z}' /etc/passwd   

//统计系统中使用bash作为解释器的用户,使用nologin的用户,还有其他用户的数量,变量如果作为运算使用,并且初始值是0的 ,可以省略定义过程

数组可以用来收集信息

for循环可以循环输出数组的下标

cat abc.txt

a[abc]=0   a[abc]++    a[abc]=1
a[xyz]=0    a[xyz]++    a[xyz]=1
a[abc]=1    a[abc]++   a[abc]=2
awk '{a[$1]++}END{print a["abc"],a["xyz"]}' abc.txt  //根据上述结果,得到如果
使用{a[$1]++}走完所有行便可收集到a[xyz]=1和a[abc]=2的结果,所以
在最后使用END任务输出a[abc]和a[xyz]的值就是 2和 1

awk '{a[$1]++}END{for(i in a){print i,a[i]}}' abc.txt  //使用for循环,循环显示
数组a的下标,与值,其中for(i in a)里面的i是变量,代表下标,in是语法不
能变,a是数组名

awk '{a[$1]++}END{for(i in a){print i,a[i]}}' /var/log/httpd/access_log  //将上述
的abc.txt文件替换成网站的日志,就可以最终用来查看日志得到可以得到
哪个ip来访以及来访的次数

awk '{ip[$1]++}END{for(i in ip){print ip[i],i} }'  /var/log/httpd/access_log  | sort -nr
查看日志中某个ip的出现次数,以及ip,然后按降序排列,出现次数最大的
显示在第一行,sort命令可以实现排序效果,-n是以数字排序,-r是降序

awk '/Failed password for root/{ip[$11]++}END{for(i in ip){print ip[i],i}}' /var/log/secure
//查看哪个ip登录root账户时输入错了密码,先输出次数,再输出ip
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值