学习grep、sed、awk之前,肯定是要先了解正则表达式。

image

学习之前,我们要先建立两个文件来练习。

vim a.txt

cp /etc/passwd passwd

第一章 grep和正则表达式

一、 正则表达式

1、单个字符

特定字符:某个具体字符(grep '1' passwd)

范围内字符: []括号里边代表的是1个字符。

数字字符:[0-9],[259]

小写字符:[a-z]

大写字符:[A-Z]

例:

grep '[0-9]' passwdgrep '[259]' passwd

grep '[a-z]' passwd

grep '[a-zA-Z]' passwd (包括所有字母)

反向字符:^

取反:[^0-9] , [^0] (‘^’一定要放倒中括号里边才行)

grep '[^0-9]' passwd(过滤以数字开头的行)

任意字符:  .

.代表任何1个字符。

2、边界字符:头尾字符

^:表示以某字符开头。(注意[^]的意思是取反)

$:表示以某字符结尾。

例如:grep '^root' passwdgrep 'bash$' passwd

^$:表示空行。

元字符(代表普通字符或特殊字符)

\w:匹配任何字类字符(数字、字母、下划线)

\W: 匹配任何非字类字符(数字、字母、下划线)

\b:代表单词分隔

例:grep '\w' passwd

grep '\W' passwd

grep '\bx\b' passwd

字符串   ‘root’‘1000’‘n…x’

[A-Z][a-z]:匹配出挨在一起的2个大小字母,如Gz、Af、Td

[0-9][0-9]:匹配挨在一起的2位数,如45,56,28,96

3、重复字符

*0次或者多次匹配前面的字符

+1次或者多次匹配前面的字符(+不能直接用,需要加\来转义)

?:0次或1次匹配前面的字符(?不能直接用,需要加\来转义)

例:grep 'se*' a.txt

grep 'se\+' a.txt

grep 'se\?' a.txt

如果要匹配多字符重复,需要用括号将多字符括起来。

例:

grep '\(se\)*' a.txt    注意()不能直接使用,需要转义,前边加\。

重复特定次数:  {n,m}  代表重复n-m次

那么我们就可以这样理解为:

*:{0,1}

+:{1,}

?: {0,1}

例:过滤重复数字2-3次的行

grep '[0-9]\{2,3\}' passwd     注意:{}也是需要转义的符号,前边加\.

任意字符串的表示: .*

例:^r.* 表示以r开头的任意字符串。

n.*x:表示n和x之间有任意个字符

n...x:表示n和x之间有3个任意字符

逻辑或: | (也是需要转义,前边加\)

例:过滤掉#开头的行和空行

grep -v '^$\|^#' nginx.conf(-v是取反的意思)

案例:

1、 匹配4-10位的QQ号码

grep '^[0-9]\{4,10\}$' a.txt

2、 匹配15或者18位×××号(支持带X的)

分析,×××开始位不能为0,结尾包括x,中间部分是13位或16数字重复。(注意转义符号)

grep '^[1-9]\([0-9]\{13\}\|[0-9]\{16\}\)[0-9xX]$' a.txt

3、 匹配密码(由数字、字母和下划线组成)

grep '^\w\+$' a.txt

说明:

grep高亮显示:grep =’grep –color=auto’这样写只是临时生效,断开重新连接后就不行了。如果想永久生效,可以写进全局变量文件中:/etc/profile

在文件的结尾添加:

alias grep='grep --color=auto'

[root@rescue ~]# source /etc/profile

这样就可以了。

第二章 巧妙破解sed

1、 sed是如何进行文本处理的?

image

(1)命令行格式

sed [options] ‘command’ file(s)

optiones(选项): -e ; -n

command命令:行定位(正则)+sed命令(操作)

1sed操作命令

-p 打印相关的行,要和-n参数一起使用。

例:sed -n 'p' passwd如果不加-n会每行显示两次。

定位1行:x/正则/       用x(代表数字)或者正则表达式来定位,正则两边要加/隔开。

例:打印第10行的内容。

sed -n '10p' passwd

sed -n '/redis/p' passwd

定位多行:x,y 或者/正则/

例:打印10-20行的内容:

nl passwd |sed -n '10,20p'

nl passwd |sed -n '/uucp/,/redis/p'两个例子的效果是一样的。

打印除第10行的所有内容:用“!”

nl passwd |sed -n '10!p'

打印除10-20的所有行:

nl passwd |sed -n '10,20!p'

定位间隔几行:x~y

例:间隔5行打印

nl passwd |sed -n '1~5p'

基本操作命令(2

a(新增行)

i (插入行)

c(替代行)

d(删除行)

例:在第5行后面增加“=========”

nl passwd |sed '5a =========='

在1-5行后分辨增加“=========”

nl passwd |sed '1,5a =========='

在第5行前面插入“=========”

nl passwd |sed '5i =========='

在1-5行前分辨插入“=========”

nl passwd |sed '1,5i =========='

替换22行内容为“11111”

nl passwd | sed '22c 11111'

22-24行替换为“11111”

nl passwd | sed '20,24c 111111111'

删除“redis”行

nl passwd |sed '/redis/d'

实战应用一:优化服务器配置

在ssh的配置文件行尾加入相应文本:

Port 52112

PermitRootLogin no

[root@rescue ~]# sed '$a \ Port 52112 \n PermitRootLogin no' ssh_config

解释一下:

$a代表在行尾增加

\Port 52112在前边加“\和两个空格是为了对齐,\为转义符”

\n表示回车

如果:[root@rescue ~]# sed -i '$a \ Port 52112 \n PermitRootLogin no' ssh_config

其中-i表示直接修改源文件

实例2、删除a.txt文本中的空行

sed '/^$/d' a.txt由于^$属于正则,所以要用//隔离起来。

实例3、服务器日志处理

找出log日志中error信息。

sed -n '/error/p' secure

基本操作命令(2

-s(替换):原内容/,#替换后内容,其中/,#随便一个都可以

例:将passwd文件中的nologin全部替换为qqqqq

sed 's/nologin/qqqqqqqqqq/' passwd

-g(全局)

例:将passwd文件中所有的:替换为%

sed 's/:/%/g' passwd

实战应用:

筛选数据,筛选出eth0的ip。(思路,将IP前后的内容全部替换为空)

ifconfig eth0 |sed -n '/inet/p' |sed 's/inet.*r://'|sed 's/B.*$//'

高级操作命令:

{}:多个sed命令同时使用,用;分开

例如:在passwd文件中删除20-24行,并替换nologin为qqq

nl passwd |sed '{20,24d;s/nologin/qqqq/}'

n:读取下一个输入行(用下一个命令处理)

例如:打印偶数行:

nl passwd |sed -n '{n;p}'或:nl passwd |sed -n '1~2p'

打印奇数行:

nl passwd |sed -n '{p;n}'或nl passwd |sed -n '2~2p'

&:替换固定字符串

例:passwd文件中的用户名后边加空格

sed 's/^[a-z_-]\+/& ' passwd

解释:

^[a-z_-]的意思是以a-z任意字母开头后边跟横线的内容

+的意思是重复1或者多次。

&的后边跟着一个空格,&代表的是前面^[a-z_-]。

大小写转换

\u     表示对首字母转换为大写

\l      对首字母转换为小写

\U    对一串字符转换成大写

\L     对一串字符转换成小写

案例一:将用户名的首字母转换为大写

[root@rescue ~]# sed 's/^[a-z_-]\+/\u/' passwd

\(   \)  替换某种(部分)字符串 \1,\2

\1就代表第一个括号中的内容,\2就代表第二个括号中的内容

例:获取eth0网卡的IP地址

ifconfig eth0 |sed -n '/inet/p' |sed 's/ine.*r:\([0-9.]\+\) .*$/\1/'

r:复制指定文件插入到匹配行

w:复制匹配行拷贝指定文件里

例:文件123.txt

[root@rescue ~]# cat 123.txt

3823098908230

3823232343

833121332文件abc.txt

[root@rescue ~]# cat abc.txt

dasajlkl

asgfsdfsfsd

ferewejlfdas

现将读取123.txt的内容插入到abc.txt的第一行之后

sed '1r 123.txt' abc.txt

复制123.txt内容到abc.txt的第一行之后

sed '1w abc.txt' 123.txt

q:退出sed

例:匹配到第10行后退出sed

nl passwd |sed '10q'

第三章 轻松玩转awk

alk是一款文本与数据处理工具,可以统计、制表、编程等。

命令格式:

awk [option] ‘command’ file

awk的内置参数一:

$0:       表示当前整个行

$1:   每行第一个字段

$2:   每行第二个字段

$3:   每行第三个字段

分隔符: -F

例:打印passwd文件中的用户名一列

awk -F ':' '{print $1}' passwd

打印用户名和UID两列     

awk -F ':' '{print $1,$3}' passwd                       打印两项内容用都好隔开

或:awk -F ':' '{print $1" "$3}' passwd          双引号中间加一个空格。

增加用户名和UID两列说明字符:

awk -F ':' '{print "User:"$1"\t""UID:"$3}' passwd

“User:”和”UID”是$1和$3前边增加的说明,”\t”表示的是table键。

awk的内置参数二:

NR:行号,每行的记录号

NF:列号,字段数量变量

FILENAME:正在处理的文件名

例:

[root@rescue ~]# awk -F ':' '{print NR,NF}' passwd

案例一:

显示/etc/passwd每行的行号,每行的列数,对应行的用户名(两种方法:print,printf)

方法一:awk -F ':' '{print "Line:"NR, "Col:"NF,"User:"$1}' passwd

标红部分都是字段的说明,用引号引起来。

方法二:awk -F ':' '{printf("Line:%s Col:%s User:%s\n",NR,NF,$1)}' passwd

\n表示回车符,不加的话不会断行。

案例二:

显示/etc/passwd中用户ID大于100的行号和用户名 (使用if….else)

awk -F ':' '{if ($3>100) print "Line:"NR,"User:"$1}' passwd

案例三:

在服务器log中找出“error”的发生日期

方法一:sed -n '/error/p' secure | awk '{print $1,$2,$3}'

方法二:awk '/error/{print $1,$2,$3}' secure

awk——逻辑判断式

~:匹配正则表达式

!~:不匹配正则表达式

==: 等于

!=:不等于

<:小于

>:大于

例1:匹配passwd文件第一个字段是否为m,是m则打印出来

awk -F ':' '$1~/^m.*/{print $1}' passwd

例2:匹配passwd文件中UID大于100的则输出用户名和UID

awk -F ':' '$3>100{print $1,$3}' passwd

awk——扩展格式

BEDIN{print “start”} command END {PRINT “END”}

例:

awk -F ':' 'BEGIN{print "Line Col User"}{print NR,NF,$1}END{print"-----"FILENAME"-----"}' passwd

awk处理过程

案例一:统计当前文件夹下的文件/文件夹占用的大小

ls -l |awk 'BEGIN{size=0}{size+=$5}END{print "size is " size/1024/1024"M"}'

案例二:统计显示/etc/passwd的账户总人数

awk -F ':' 'BEGIN{count=0}$1!~/^$/{count++}END{print " count = "count}' passwd