正则表达式(Regular Expression):对字符串操作的一种逻辑公式,就是用事先定义好的一些特定字符、及这些特定字符的组合,组成一个“规则字符串”,这个“规则字符串”用来表达对字符串的一种过滤逻辑。

一、基本正则-元字符

1、字符匹配

.:任意单个字符,如r..t,可以是root、radt,但不能是rat、roooot。

*:匹配其前面字符任意次,例如

a*b:a出现任意次接着是b,比如:b、ab、aab,但不能是acb。

.:任意长度任意字符,例如:a.b,a开头,b结尾,ab中间可以是任意长度任意字符,如:ab、axb、azxeb
+:匹配前面的字符一个或多个
?:匹配前面的字符0个或1个
[]:匹配指定范围内的字符

[^]:匹配指定范围外的字符

字符的表示:

[[:digit:]]:数字

[[:lower:]]:小写字母

[[:upper:]]:大写字母

[[:punct:]]:标点符号

[[:space:]]:空白字符

[[:alpha:]]:所有字母

[[:alnum:]]:数字和字母

2、次数匹配

\?:匹配前面字符0次或1次,\为转义字符

{m,n}:匹配前面字符最少m次,最多n次

{m}:匹配前面字符m次

{m,}:匹配前面字符最少m次

{0,n}:匹配前面字符最多n次

{1,}:匹配前面字符最少1次,最多无限次

3、位置锚定

^:锚定行首,此字符后的任意内容必须出现在行首

$:锚定行尾,此字符后的任意内容必须出现在行尾

^$:空白行

\<:词首锚定,其后面的任意字符必须作为单词首部出现

>:词尾锚定,其后面的任意字符必须作为单词尾部出现

例如:

\<root:root字符必须作为单词首部出现,如rootahha

root>:root字符必须作为单词尾部出现,如ahjdlgroot

\<root>:匹配一个单词,这里是匹配root这个单词。

():分组匹配,常用于后向引用。

后向引用:引用前面的分组括号中的模式所匹配到的字符。分组括号中的模式匹配到的内容会被正则表达式引擎记录于内部的变量中,这些变量的命名方式为:\1,\2,\3…

\1:从左侧起,第1个左括号以及与之匹配的右括号之间的模式所匹配到的字符。

\2:从左侧起,第2个左括号以及与之匹配的右括号之间的模式所匹配到的字符。

二、扩展正则

字符匹配、匹配次数、位置锚定、分组匹配等含义跟基本正则一样。

三、Linux三剑客

1、第一剑客:grep

grep,全称:Global serch REgular expression and Print out the line( 全局搜索正则表达式并打印这行)。

作用:文本搜索。 用法:grep [选项] 模式 文件名

选项:

-c:表示打印符合要求的行数

-i:表示忽略大小写

-n:表示输出符合要求的行及其行号

-o:只显示匹配到的字符(串)

-q:静默模式,不输出

-r:遍历所有的子目录

-v:反向输出,也就是打印不符合要求的行

-A n:A后面跟一个数字n,表示打印符合要求的行及其下面n行

-B n:B后面跟一个数字n,表示打印符合要求的行及其上面面n行

-C n:C后面跟一个数字n,打印符合要求的行及其上下面各n行

egrep:默认支持正则表达式,而grep要使用正则表达式,则需要使用-E选项。

用法举例:

以下例子,均以root用户演示

例1: 显示/etc/passwd文件中以大小写字母s开头的行及其行号

[root@node5 ~]# grep -in '^s' /etc/passwd
6:sync:x:5:0:sync:/sbin:/bin/sync
7:shutdown:x:6:0:shutdown:/sbin:/sbin/shutdown
14:systemd-network:x:192:192:systemd Network Management:/:/sbin/nologin
17:sshd:x:74:74:Privilege-separated SSH:/var/empty/sshd:/sbin/nologin
[root@node5 ~]# 

或者:

[root@node5 ~]# grep -n '^[Ss]' /etc/passwd
6:sync:x:5:0:sync:/sbin:/bin/sync
7:shutdown:x:6:0:shutdown:/sbin:/sbin/shutdown
14:systemd-network:x:192:192:systemd Network Management:/:/sbin/nologin
17:sshd:x:74:74:Privilege-separated SSH:/var/empty/sshd:/sbin/nologin
[root@node5 ~]# 

例2: 显示/etc/passwd中不以/bin/bash结尾的行

[root@node5 ~]# grep -v '/bin/bash' /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
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
games:x:12:100:games:/usr/games:/sbin/nologin
ftp:x:14:50:FTP User:/var/ftp:/sbin/nologin
nobody:x:99:99:Nobody:/:/sbin/nologin
systemd-network:x:192:192:systemd Network Management:/:/sbin/nologin
dbus:x:81:81:System message bus:/:/sbin/nologin
polkitd:x:999:998:User for polkitd:/:/sbin/nologin
sshd:x:74:74:Privilege-separated SSH:/var/empty/sshd:/sbin/nologin
postfix:x:89:89::/var/spool/postfix:/sbin/nologin
nginx:x:998:996::/home/nginx:/sbin/nologin
mysql:x:997:995::/home/mysql:/sbin/nologin
[root@node5 ~]# 

例3: 显示/etc/passwd文件中root用户的shell类型

[root@node5 ~]# grep '^root' /etc/passwd | cut -d: -f7
/bin/bash
[root@node5 ~]# 

或者:

[root@node5 ~]# grep '^root\>' /etc/passwd | cut -d: -f7
/bin/bash
[root@node5 ~]# 

例4: 找出/etc/passwd中的两位数或三位数。

[root@node5 ~]# grep '\<[0-9]\{2,3\}\>' /etc/passwd
mail:x:8:12:mail:/var/spool/mail:/sbin/nologin
operator:x:11:0:operator:/root:/sbin/nologin
games:x:12:100:games:/usr/games:/sbin/nologin
ftp:x:14:50:FTP User:/var/ftp:/sbin/nologin
nobody:x:99:99:Nobody:/:/sbin/nologin
systemd-network:x:192:192:systemd Network Management:/:/sbin/nologin
dbus:x:81:81:System message bus:/:/sbin/nologin
polkitd:x:999:998:User for polkitd:/:/sbin/nologin
sshd:x:74:74:Privilege-separated SSH:/var/empty/sshd:/sbin/nologin
postfix:x:89:89::/var/spool/postfix:/sbin/nologin
nginx:x:998:996::/home/nginx:/sbin/nologin
mysql:x:997:995::/home/mysql:/sbin/nologin

例5: 判断root用户是否登录,登录则显示在线,不登录显示不在线

[root@node5 ~]# who | grep '^root\>' &> /dev/null && echo "root is online..." || echo "root is down..."
root is online...
[root@node5 ~]# 

例6: 显示root、ftp用户的UID和默认SHELL。

[root@node5 ~]# grep -E '^(root|ftp)\>' /etc/passwd | cut -d: -f3,7
0:/bin/bash
14:/sbin/nologin
[root@node5 ~]# 

或者:

[root@node5 ~]# egrep '^(root|ftp)\>' /etc/passwd | cut -d: -f3,7
0:/bin/bash
14:/sbin/nologin
[root@node5 ~]# 

例7: 显示 /etc/ssh/sshd_config的内容,但不显示空白行和注释

[root@node5 ~]# grep  -v "^$\|^#"  /etc/ssh/sshd_config 
HostKey /etc/ssh/ssh_host_rsa_key
HostKey /etc/ssh/ssh_host_ecdsa_key
HostKey /etc/ssh/ssh_host_ed25519_key
SyslogFacility AUTHPRIV
AuthorizedKeysFile  .ssh/authorized_keys
PasswordAuthentication yes
ChallengeResponseAuthentication no
GSSAPIAuthentication yes
GSSAPICleanupCredentials no
UsePAM yes
X11Forwarding yes
AcceptEnv LANG LC_CTYPE LC_NUMERIC LC_TIME LC_COLLATE LC_MONETARY LC_MESSAGES
AcceptEnv LC_PAPER LC_NAME LC_ADDRESS LC_TELEPHONE LC_MEASUREMENT
AcceptEnv LC_IDENTIFICATION LC_ALL LANGUAGE
AcceptEnv XMODIFIERS
Subsystem   sftp    /usr/libexec/openssh/sftp-server
[root@node5 ~]# 
2、第二剑客:sed

sed,全称:Stream EDitor(流编辑器)。

sed模式空间:默认不是编辑原文件,仅对模式空间中的数据做处理,而后,处理后,将模式空间打印到屏幕。

命令格式:sed [选项] AddressCommand file

•选项:

-n:静默模式(不显示模式空间)

-i:直接修改原文件

-e:多点编辑,也就是实现多个行为。

-f:从指定文件中读取编辑脚本

-r:扩展表达式

•Address:地址定界

Address,地址定界,也就是对什么范围进行操作,如果不指定地址,则对全文进行处理。其类型有:

1、StartLine,EndLine

例如,从1到5行:1,5

从1到最后一行:1,$

2、/RegEXP/

正则表达式,如:/^root/

3、/patten1/,/patten2/

第1次被patten1匹配到的行开始到第1次被patten2匹配到的行结束,这中间的所有行

4、LineNumber:指定的行,第某行

5、StartLine,+N:从StartLine开始,向后的N行(共N+1行)

•Command:处理命令

d:删除符合条件的行

p:打印符合条件的行

!:取反

h:把模式空间的内容覆盖至保存空间中

H:把模式空间的内容追加至保存空间中

g:从保持空间取出数据覆盖至模式空间

G:从保持空间取出数据追加至模式空间

x:把模式空间的内容与保持空间中的内容互换

n:读取匹配到的行的下一行至模式空间中

N:追加匹配到的行的下一行至模式空间中

D:删除多行模式空间中的所有行

n;p:打印偶数行

n;d:打印奇数行

a \string:在符合(指定行)后面追加新行,内容为string

i \string:在符合(指定行)前面追加新行,内容为string

内容替换:

sed [选项] ‘s/str1/str2/g|i’文件

s:替换

g:全局替换,如果不写,则替换第一个匹配到的内容

i:不区分大小写

例1:打印/etc/passwd文件的第3行

[root[@localhost~]#sed -n '3'p /etc/passwd
daemon:x:2:2:daemon:/sbin:/sbin/nologin

例2:打印/etc/passwd文件的3到6行

[root[@localhost~]#sed -n '3,6'p /etc/passwd
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

例3:打印/etc/passwd文件中含有root的行

[root[@localhost~]#sed -n '/root/'p /etc/passwd
root:x:0:0:root:/root:/bin/bash
operator:x:11:0:operator:/root:/sbin/nologin

例4:在/etc/passwd文件中含有root的行的后面添加新的行,内容为#hello,world。

[root[@localhost~]#sed  '/root/a \#hello,world' /etc/passwd  
root:x:0:0:root:/root:/bin/bash
#hello,world
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
#hello,world

例5:在/etc/passwd文件中含有root的行的前面面添加新的行,内容为****HAHA****

[root[@localhost ~]#sed  '/root/i \****HAHA****' /etc/passwd             
****HAHA****
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
****HAHA****
operator:x:11:0:operator:/root:/sbin/nologin

例6:打印/etc/passwd文件中第1行及其向下3行。

[root@localhost ~]#sed -n '1,+3'p /etc/passwd 
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

例7:假设/root/test.txt内容为:

111

222

333

444

555

使用sed命令实现以下需求:

打印偶数行、奇数行、最后2行、最后1行、逆向显示该文件。

偶数行:

[root@localhost ~]#sed -n 'n;p' /root/test.txt
222
444

奇数行:

[root@localhost ~]#sed  'n;d' /root/test.txt  
111
333
555

逆向显示:

[root@localhost ~]#sed -n '1!G;h;$p' /root/test.txt
555
444
333
222
111

最后2行:

[root@localhost ~]#sed  '$!N;$!D' /root/test.txt  
444
555

最后1行:

[root@localhost ~]#sed '$!d' /root/test.txt
555

或者:

[root@localhost ~]#sed '$!D' /root/test.txt 
555

例8:-e选项演示

[root@localhost ~]#sed -n  -e '1'p -e '/222/'p /root/test.txt 
111
222

例9:字符串替换。将/root/passwd文件第一行的ot换成to。

[root@localhost ~]#sed '1s/ot/to/g' /root/passwd  
roto:x:0:0:roto:/roto:/bin/bash

例10:字符串位置调换。

[root@localhost ~]#sed -r 's/(root)(.*)(bash)/\3\2\1/g' /root/passwd
bash:x:0:0:root:/root:/bin/root

上面的例子中都不会修改原文件内容,如果要直接修改原文件,则添加-i选项即可。例如:

[root@localhost ~]#sed -i 's/11/AA/g' /root/test.txt 
[root@localhost ~]#cat test.txt 
AA1
222
333
444
555
3、第三剑客:awk

awk:报告生成器,格式化文本输出

基本用法:awk [option] ‘program’ 文件

标准格式:awk -F ‘:’ ‘BEGIN{语句} {if(条件){语句1;语句2;语句3} } END{语句}’ filename

[root@node5 ~]# awk  'BEGIN{FS=":"} {$1="ROOT";print $1} END{}' /etc/passwd
ROOT
ROOT
ROOT
ROOT
ROOT
ROOT
ROOT
ROOT
ROOT
ROOT
ROOT
ROOT
ROOT
ROOT
ROOT
ROOT
ROOT
ROOT

选项:

-F:指定输入分隔符。后面紧跟单引号,分隔符写在单引号内,默认是空格或tab,例如:-F ‘:’ 指定冒号为分隔符。

-v:自定义变量,格式:-v var=value,变量名区分大小写。

program:pattern{action statements}

pattern:模式匹配

action statements:执行语句,语句之间用逗号分隔。

•3.1 内置变量

$0:当前记录

$1…$n:当前记录的第1….第n个字段

FS:input field separate,输入分隔符,默认为空白字符

OFS:output field separate,输出分隔符

RS:input record separate,输入时的换行符

ORS:output record separate,输出时的换行符

NF:number field,字段数

NR:number of record,行数

•3.2 BEGIN和END模块

通常,对于每个输入行,awk都会执行每个脚本代码块一次,在执行代码块之前,定义BEGIN块,那么就会执行BEING块,再执行脚本代码块。

END块,处理了输入文件的所有行之后再执行END块。通常,END块用于执行最终计算或打印应该出现在输出流结尾的信息。

•3.3 运算符

赋值运算符:

= += -= *= %= ^=(求幂) **=(求幂)

例如:

[root@localhost ~]#awk 'BEGIN{a=1;a+=2;print a}'
3
[root@localhost ~]#awk 'BEGIN{a=2;a**=2;print a}' 
4
[root@localhost ~]#awk 'BEGIN{a=2;a^=2;print a}'  
4

逻辑运算符:

|| 逻辑或 && 逻辑与

例如:

[root@localhost ~]#awk 'BEGIN{a=1;b=2;print(a>2&&b>1,a=1||b>1)}'
0 1

正则运算符:

~ 匹配正则 !~ 不匹配正则

例如:

[root@localhost ~]#awk 'BEGIN{a="100test";if(a~/100/)print "ok"}'
ok

打印/etc/passwd第一行包含oo的行:

[root@node5 ~]# awk -F ':' '$1 ~/oo/' /etc/passwd
root:x:0:0:root:/root:/bin/bash

关系运算符:

< <= > >= == !=

数字关系比较,这个没什么悬念;字符串的比较,按照ascii码顺序比较。

[root@localhost ~]#awk 'BEGIN{a="11";if(a>9)print "OK";else print "Wrong"}'
Wrong
[root@localhost ~]#awk 'BEGIN{a=11;if(a>9)print "OK";else print "Wrong"}'  
OK
[root@localhost ~]#awk 'BEGIN{ab;if(ab==b)print "OK";else print "Wrong"}'
OK

算术运算符:

+  -  *  / 

所有进行算术运算的操作数都转为数值,非数值的操作数都转为数值0。

[root@localhost ~]#awk 'BEGIN{a=="b";print a++,++a}'
0 2
[root@localhost ~]#awk 'BEGIN{a=="11b4";print a++,++a}'  
0 2

其他运算符:

?: 三目运算符

[root@localhost ~]#awk 'BEGIN{a="b";print a==1?"ok":"error"}'
error

•3.4 数学运算

1、统计某个字段的总和

[root@localhost ~]#awk -F ':' '{(tot=tot+$3)};END{print tot}' /etc/passwd
5733

2、统计tcp连接状态的个数

[root@localhost ~]#netstat -tan | awk '/^tcp\>/ {state[$NF]++} END{for(i in state){print i,state[i]}}'
LISTEN 6
ESTABLISHED 1

3、统计/etc/fatab文件中每个文件类型出现的次数

[root@localhost ~]#awk '/^[^#]/{fs[$3]++} END{for(i in fs){print i,fs[i]}}' /etc/fstab
swap 1
ext3 1
ext4 1

•3.5 例子

1、获取当前系统的ip

[root@localhost ~]#ifconfig  | awk -F ':' 'NR==2{print}' | awk '{print $2}'
192.168.10.206
[root@localhost ~]#ifconfig | awk -F[" ":]+  'NR==2{print $3}'
192.168.10.206
[root@localhost ~]#ifconfig | awk   'NR==2{print $2}'
192.168.10.206

2、OFS用法

[root@localhost ~]#head -5 /etc/passwd | awk -F ':' '{OFS="#"} {print $1,$2,$3,$4,$5}'
root#x#0#0#root
bin#x#1#1#bin
daemon#x#2#2#daemon
adm#x#3#4#adm
lp#x#4#7#lp

3、NF、NR用法

[root@localhost ~]#cat  /etc/passwd | awk -F ':' 'NR==1{print NF}'
7

sed扩展:http://https://coolshell.cn/articles/9104.html

awk中gsub函数的使用 http://ask.apelearn.com/question/200

awk 截取指定多个域为一行 http://ask.apelearn.com/question/224

过滤两个或多个关键词 http://ask.apelearn.com/question/198

用awk生成以下结构文件 http://ask.apelearn.com/question/5494

打印某行到某行之间的内容http://ask.apelearn.com/question/559

sed转换大小写 http://ask.apelearn.com/question/7758

sed在某一行最后添加一个数字http://ask.apelearn.com/question/288

删除某行到最后一行 http://ask.apelearn.com/question/213

参考 https://coolshell.cn/articles/9104.html
参考 http://www.cnblogs.com/51linux/archive/2011/09/24/2189420.html
参考 https://www.cnblogs.com/f-ck-need-u/p/7496916.html

分类: Linux基础

发表评论

电子邮件地址不会被公开。 必填项已用*标注

2 × 2 =