3.文本处理三剑客
- grep 命令主要对文本的(正则表达式)行基于模式进行过滤
- sed:stream editor,文本编辑工具
- awk:Linux上的实现gawk,文本报告生成器
3.1 文本处理三剑客之 grep
grep: Global search REgular expression and Print out the line
作用:文本搜索工具,根据用户指定的“模式”对目标文本逐行进行匹配检查;打印匹配到的行
模式:由正则表达式字符及文本字符所编写的过滤条件
格式:
grep [OPTIONS] PATTERN [FILE...]
常见选项:
--color=auto 对匹配到的文本着色显示
-m # 匹配#次后停止
-v 显示不被pattern匹配到的行
-i 忽略字符大小写
-n 显示匹配的行号
-c 统计匹配的行数
-o 仅显示匹配到的字符串
-q 静默模式,不输出任何信息
-A # after, 后#行
-B # before, 前#行
-C # context, 前后各#行
-e 实现多个选项间的逻辑or关系,如:grep –e 'cat' -e 'dog' file
-w 匹配整个单词
-E 使用ERE,相当于egrep
-F 不支持正则表达式,相当于fgrep
-f file 根据模式文件处理
-r 递归目录,但不处理软链接
-R 递归目录,但处理软链接
范例:
[root@rocky8 ~]# grep rocky
i am raymond
rocky8
rocky8
i am study rocky8 linux
i am study rocky8 linux
^C
#默认等待输入,输入包含字符,就打印整行,并标红包含的字符
[root@rocky8 ~]# cat /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
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:65534:65534:Kernel Overflow User:/:/sbin/nologin
dbus:x:81:81:System message bus:/:/sbin/nologin
systemd-coredump:x:999:997:systemd Core Dumper:/:/sbin/nologin
systemd-resolve:x:193:193:systemd Resolver:/:/sbin/nologin
tss:x:59:59:Account used for TPM access:/dev/null:/sbin/nologin
polkitd:x:998:996:User for polkitd:/:/sbin/nologin
unbound:x:997:994:Unbound DNS resolver:/etc/unbound:/sbin/nologin
sssd:x:996:993:User for sssd:/:/sbin/nologin
sshd:x:74:74:Privilege-separated SSH:/var/empty/sshd:/sbin/nologin
postfix:x:89:89::/var/spool/postfix:/sbin/nologin
raymond:x:1000:1000::/home/raymond:/bin/bash
boss:x:1001:1001::/home/boss:/bin/bash
[root@rocky8 ~]# cat /etc/passwd |grep root
root:x:0:0:root:/root:/bin/bash
operator:x:11:0:operator:/root:/sbin/nologin
#通过管道 接收标准输入,找到包含的字符的行
[root@rocky8 ~]# grep root /etc/passwd #grep 本身支持后边跟文件
root:x:0:0:root:/root:/bin/bash
operator:x:11:0:operator:/root:/sbin/nologin
[root@rocky8 ~]# cut -d: -f1 /etc/passwd | grep root
root
#把前面命令的执行结果,用grep 过滤
[root@rocky8 ~]# pstree -p |grep bash
|-sshd(750)---sshd(838)---sshd(979)---bash(998)-+-grep(1389)
[root@rocky8 ~]# grep root /etc/passwd /etc/group
/etc/passwd:root:x:0:0:root:/root:/bin/bash
/etc/passwd:operator:x:11:0:operator:/root:/sbin/nologin
/etc/group:root:x:0:
#可以对多个文件进行处理
[root@rocky8 ~]# alias grep
alias grep='grep --color=auto' #命令别名定义了颜色
[root@rocky8 ~]# \grep root /etc/passwd /etc/group
/etc/passwd:root:x:0:0:root:/root:/bin/bash
/etc/passwd:operator:x:11:0:operator:/root:/sbin/nologin
/etc/group:root:x:0:
#原始命令不自动加颜色
[root@rocky8 ~]# which grep
alias grep='grep --color=auto'
/usr/bin/grep
[root@rocky8 ~]# /usr/bin/grep root /etc/passwd /etc/group
/etc/passwd:root:x:0:0:root:/root:/bin/bash
/etc/passwd:operator:x:11:0:operator:/root:/sbin/nologin
/etc/group:root:x:0:
#也可以用路径使用原始命令,但是内部命令没有路径,就不能用路径,这个方法有一点的局限性
[root@rocky8 ~]# grep bin /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
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:65534:65534:Kernel Overflow User:/:/sbin/nologin
dbus:x:81:81:System message bus:/:/sbin/nologin
systemd-coredump:x:999:997:systemd Core Dumper:/:/sbin/nologin
systemd-resolve:x:193:193:systemd Resolver:/:/sbin/nologin
tss:x:59:59:Account used for TPM access:/dev/null:/sbin/nologin
polkitd:x:998:996:User for polkitd:/:/sbin/nologin
unbound:x:997:994:Unbound DNS resolver:/etc/unbound:/sbin/nologin
sssd:x:996:993:User for sssd:/:/sbin/nologin
sshd:x:74:74:Privilege-separated SSH:/var/empty/sshd:/sbin/nologin
postfix:x:89:89::/var/spool/postfix:/sbin/nologin
raymond:x:1000:1000::/home/raymond:/bin/bash
boss:x:1001:1001::/home/boss:/bin/bash
[root@rocky8 ~]# grep -m 3 bin /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
#-m 可以指定查看包含字符串前几行
[root@rocky8 ~]# grep -v nologin /etc/passwd
root:x:0:0:root:/root:/bin/bash
sync:x:5:0:sync:/sbin:/bin/sync
shutdown:x:6:0:shutdown:/sbin:/sbin/shutdown
halt:x:7:0:halt:/sbin:/sbin/halt
raymond:x:1000:1000::/home/raymond:/bin/bash
boss:x:1001:1001::/home/boss:/bin/bash
#-v 显示不包含字符串的行
[root@rocky8 ~]# grep -n nologin /etc/passwd
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
9:mail:x:8:12:mail:/var/spool/mail:/sbin/nologin
10:operator:x:11:0:operator:/root:/sbin/nologin
11:games:x:12:100:games:/usr/games:/sbin/nologin
12:ftp:x:14:50:FTP User:/var/ftp:/sbin/nologin
13:nobody:x:65534:65534:Kernel Overflow User:/:/sbin/nologin
14:dbus:x:81:81:System message bus:/:/sbin/nologin
15:systemd-coredump:x:999:997:systemd Core Dumper:/:/sbin/nologin
16:systemd-resolve:x:193:193:systemd Resolver:/:/sbin/nologin
17:tss:x:59:59:Account used for TPM access:/dev/null:/sbin/nologin
18:polkitd:x:998:996:User for polkitd:/:/sbin/nologin
19:unbound:x:997:994:Unbound DNS resolver:/etc/unbound:/sbin/nologin
20:sssd:x:996:993:User for sssd:/:/sbin/nologin
21:sshd:x:74:74:Privilege-separated SSH:/var/empty/sshd:/sbin/nologin
22:postfix:x:89:89::/var/spool/postfix:/sbin/nologin
#-n 显示包含字符串的行号
[root@rocky8 ~]# grep -c nologin /etc/passwd
18
#-c 显示包含字符串行的次数
[root@rocky8 ~]# grep -o nologin /etc/passwd
nologin
nologin
nologin
nologin
nologin
nologin
nologin
nologin
nologin
nologin
nologin
nologin
nologin
nologin
nologin
nologin
nologin
nologin
[root@rocky8 ~]# grep -o nologin /etc/passwd | wc -l
18
#-o 只显示包含字符串
[root@rocky8 ~]# grep -no nologin /etc/passwd
2:nologin
3:nologin
4:nologin
5:nologin
9:nologin
10:nologin
11:nologin
12:nologin
13:nologin
14:nologin
15:nologin
16:nologin
17:nologin
18:nologin
19:nologin
20:nologin
21:nologin
22:nologin
[root@rocky8 ~]# grep -q root /etc/passwd #-q 找到,找不到都不显示
[root@rocky8 ~]# echo $?
0 #找到了返回值为0
[root@rocky8 ~]# grep -q rooter /etc/passwd
[root@rocky8 ~]# echo $?
1 #找不到返回值为1
#通过$?返回值 ,来判断找到没找到
[root@rocky8 ~]# grep root /etc/passwd &> /dev/null
[root@rocky8 ~]# echo $?
0
[root@rocky8 ~]# grep rooter /etc/passwd &> /dev/null
[root@rocky8 ~]# echo $?
1
#也可以通过,扔到垃圾箱,来判断
[root@rocky8 ~]# grep -n root /etc/passwd
1:root:x:0:0:root:/root:/bin/bash
10:operator:x:11:0:operator:/root:/sbin/nologin
[root@rocky8 ~]# grep -nA3 root /etc/passwd
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
--
10:operator:x:11:0:operator:/root:/sbin/nologin
11-games:x:12:100:games:/usr/games:/sbin/nologin
12-ftp:x:14:50:FTP User:/var/ftp:/sbin/nologin
13-nobody:x:65534:65534:Kernel Overflow User:/:/sbin/nologin
#-A 显示包含字符串的后几行
[root@rocky8 ~]# grep -nB3 root /etc/passwd
1:root:x:0:0:root:/root:/bin/bash
--
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
#-B 显示包含字符串的前几行
[root@rocky8 ~]# grep -nC3 root /etc/passwd
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
--
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
11-games:x:12:100:games:/usr/games:/sbin/nologin
12-ftp:x:14:50:FTP User:/var/ftp:/sbin/nologin
13-nobody:x:65534:65534:Kernel Overflow User:/:/sbin/nologin
#-C 显示包含字符串的前几行和后几行
[root@rocky8 ~]# grep -e root -e bash /etc/passwd
root:x:0:0:root:/root:/bin/bash
operator:x:11:0:operator:/root:/sbin/nologin
raymond:x:1000:1000::/home/raymond:/bin/bash
boss:x:1001:1001::/home/boss:/bin/bash
#-e 可以加多次过滤条件,表示包含root或者包含bash
[root@rocky8 ~]# grep root /etc/passwd | grep bash
root:x:0:0:root:/root:/bin/bash
#并且 ,用管道再过滤一次
[root@rocky8 ~]# echo hello |grep -w hello
hello
[root@rocky8 ~]# echo helloeveryone |grep -w hello
[root@rocky8 ~]# echo hello:everyone |grep -w hello
hello:everyone
[root@rocky8 ~]# echo hello,everyone |grep -w hello
hello,everyone
[root@rocky8 ~]# echo hello-everyone |grep -w hello
hello-everyone
[root@rocky8 ~]# echo hello_everyone |grep -w hello
[root@rocky8 ~]# echo hello2everyone |grep -w hello
[root@rocky8 ~]# echo hello everyone |grep -w hello
hello everyone
#-w 匹配单词,连续的字母、数字、_ 下划线才是单词,其他的字符分割都不算单词
[root@rocky8 ~]# cd /data
[root@rocky8 data]# cat >f1.txt <<EOF
raymond
boss
EOF
[root@rocky8 data]# cat f1.txt
raymond
boss
[root@rocky8 data]# cat >f2.txt <<EOF
I am oldraymond
bigboss
I love linux
I am linux student
EOF
[root@rocky8 data]# cat f2.txt
I am oldraymond
bigboss
I love linux
I am linux student
[root@rocky8 data]# grep -f f1.txt f2.txt
I am oldraymond
bigboss
#-f 拿第一个文件作为过滤条件,看第二个文件,是不是包含第一个文件的字符串,如果包含就把整行显示出来
范例:取两个文件的相同行
[root@rocky8 data]# cat test1.txt
a
b
1
c
[root@rocky8 data]# cat test2.txt
b
e
f
c
1
2
[root@rocky8 data]# grep -f test1.txt test2.txt
b
c
1
范例:
[root@rocky8 data]# ls -R /etc
[root@rocky8 data]# grep -r root /etc #-r 递归查看目录包含字符串的行,不处理软链接
[root@rocky8 data]# grep -R root /etc #-R 递归查看目录包含字符串的行,但处理软链接
范例:
[root@rocky8 data]# grep root /etc/passwd
root:x:0:0:root:/root:/bin/bash
operator:x:11:0:operator:/root:/sbin/nologin
[root@rocky8 data]# grep "USER" /etc/passwd
[root@rocky8 data]# grep 'USER' /etc/passwd
[root@rocky8 data]# grep whoami /etc/passwd
范例:
[root@rocky8 data]# df | grep '^/dev/sd' |tr -s ' ' %|cut -d% -f5|sort -n|tail -1
19
范例:
[root@rocky8 data]# grep "^ESTAB" ss2.log |tr -s ' ' : |cut -d: -f6|sort |uniq -c|sort -nr|head -n3
12 223.88.255.148
10 183.202.63.36
9 117.152.155.119
范例:
[root@rocky8 data]# grep -v "^#" /etc/profile | grep -v '^$'
pathmunge () {
case ":${PATH}:" in
*:"$1":*)
;;
*)
if [ "$2" = "after" ] ; then
PATH=$PATH:$1
else
PATH=$1:$PATH
fi
esac
}
if [ -x /usr/bin/id ]; then
if [ -z "$EUID" ]; then
# ksh workaround
EUID=`/usr/bin/id -u`
UID=`/usr/bin/id -ru`
fi
USER="`/usr/bin/id -un`"
LOGNAME=$USER
MAIL="/var/spool/mail/$USER"
fi
if [ "$EUID" = "0" ]; then
pathmunge /usr/sbin
pathmunge /usr/local/sbin
else
pathmunge /usr/local/sbin after
pathmunge /usr/sbin after
fi
HOSTNAME=`/usr/bin/hostname 2>/dev/null`
HISTSIZE=1000
if [ "$HISTCONTROL" = "ignorespace" ] ; then
export HISTCONTROL=ignoreboth
else
export HISTCONTROL=ignoredups
fi
export PATH USER LOGNAME MAIL HOSTNAME HISTSIZE HISTCONTROL
if [ $UID -gt 199 ] && [ "`/usr/bin/id -gn`" = "`/usr/bin/id -un`" ]; then
umask 002
else
umask 022
fi
for i in /etc/profile.d/*.sh /etc/profile.d/sh.local ; do
if [ -r "$i" ]; then
if [ "${-#*i}" != "$-" ]; then
. "$i"
else
. "$i" >/dev/null
fi
fi
done
unset i
unset -f pathmunge
if [ -n "${BASH_VERSION-}" ] ; then
if [ -f /etc/bashrc ] ; then
# Bash login shells run only /etc/profile
# Bash non-login shells run only /etc/bashrc
# Check for double sourcing is done in /etc/bashrc.
. /etc/bashrc
fi
fi
[root@rocky8 data]# grep -v "^#\|^$" /etc/profile
[root@rocky8 data]# grep "^[^#]" /etc/profile
[root@rocky8 data]# grep -v "^\(#\|$\)" /etc/profile
[root@rocky8 data]# grep -Ev "^(#|$)" /etc/profile
[root@rocky8 data]# egrep -v "^(#|$)" /etc/profile
[root@centos6 ~]# egrep -v '^(#|$)' /etc/httpd/conf/httpd.conf
范例:
[root@rocky8 data]# grep -o 'r..t' /etc/passwd
root
root
root
root
r/ft
范例:
[root@rocky8 data]# ifconfig | grep -E '[0-9]{1,3}.[0-9]{1,3}.[0-9]{1,3}.[0-9]{1,3}'
inet 172.31.1.8 netmask 255.255.248.0 broadcast 172.31.7.255
RX packets 9744 bytes 11614557 (11.0 MiB)
inet 127.0.0.1 netmask 255.0.0.0
[root@rocky8 data]# ifconfig | grep -E '([0-9]{1,3}.){3}[0-9]{1,3}'
inet 172.31.1.8 netmask 255.255.248.0 broadcast 172.31.7.255
RX packets 9752 bytes 11615406 (11.0 MiB)
inet 127.0.0.1 netmask 255.0.0.0
[root@rocky8 data]# ifconfig eth0 | grep -Eo '([0-9]{1,3}\.){3}[0-9]{1,3}'|head -1
172.31.1.8
[root@rocky8 data]# cat > regex.txt
([0-9]{1,3}\.){3}[0-9]{1,3}
^C
[root@rocky8 data]# ifconfig | grep -oEf regex.txt
172.31.1.8
255.255.248.0
172.31.7.255
127.0.0.1
255.0.0.0
范例:
[root@rocky8 data]# grep -E 'root|bash' /etc/passwd
root:x:0:0:root:/root:/bin/bash
operator:x:11:0:operator:/root:/sbin/nologin
raymond:x:1000:1000::/home/raymond:/bin/bash
boss:x:1001:1001::/home/boss:/bin/bash
范例:
[root@rocky8 data]# grep -w root /etc/passwd
root:x:0:0:root:/root:/bin/bash
operator:x:11:0:operator:/root:/sbin/nologin
[root@rocky8 data]# grep '\<root\>' /etc/passwd
root:x:0:0:root:/root:/bin/bash
operator:x:11:0:operator:/root:/sbin/nologin
范例:
[root@rocky8 data]# grep "^\(.*\)\>.*\<\1$" /etc/passwd
sync:x:5:0:sync:/sbin:/bin/sync
shutdown:x:6:0:shutdown:/sbin:/sbin/shutdown
halt:x:7:0:halt:/sbin:/sbin/halt
[root@rocky8 data]# grep -E "^(.*)\>.*\<\1$" /etc/passwd
sync:x:5:0:sync:/sbin:/bin/sync
shutdown:x:6:0:shutdown:/sbin:/sbin/shutdown
halt:x:7:0:halt:/sbin:/sbin/halt
[root@rocky8 data]# egrep "^(.*)\>.*\<\1$" /etc/passwd
sync:x:5:0:sync:/sbin:/bin/sync
shutdown:x:6:0:shutdown:/sbin:/sbin/shutdown
halt:x:7:0:halt:/sbin:/sbin/halt
范例:面试题,算出所有人的年龄总和
[root@rocky8 data]# cat > nianling.txt
xiaoming=20
xiaohong=18
xiaoqiang=22
^C
[root@rocky8 data]# cut -d"=" -f2 nianling.txt|tr '\n' + | grep -Eo ".*[0-9]"|bc
60
[root@rocky8 data]# grep -Eo "[0-9]+" nianling.txt | tr '\n' + | grep -Eo ".*[0-9]"|bc
60
4.正则表达式
REGEXP: Regular Expressions,由一类特殊字符及文本字符所编写的模式,其中有些字符(元字符)不表示字符字面意义,而表示控制或通配的功能,类似于增强版的通配符功能,但与通配符不同,通配符功能是用来处理文件名,而正则表达式是处理文本内容中字符
正则表达式被很多程序和开发语言所广泛支持:vim, less,grep,sed,awk, nginx,mysql 等
正则表达式分两类:
- 基本正则表达式:BRE
- 扩展正则表达式:ERE
正则表达式引擎:
采用不同算法,检查处理正则表达式的软件模块,如:PCRE(Perl Compatible Regular Expressions)
正则表达式的元字符分类:字符匹配、匹配次数、位置锚定、分组
帮助:man 7 regex
4.1 基本正则表达式元字符
4.1.1 字符匹配
. 匹配任意单个字符(除了\n),可以是一个汉字或其它国家的文字
[] 匹配指定范围内的任意单个字符,示例:[wang] [0-9] [a-z] [a-zA-Z]
[^] 匹配指定范围外的任意单个字符,示例:[^wang]
[:alnum:] 字母和数字
[:alpha:] 代表任何英文大小写字符,亦即 A-Z, a-z
[:lower:] 小写字母,示例:[[:lower:]],相当于[a-z]
[:upper:] 大写字母
[:blank:] 空白字符(空格和制表符)
[:space:] 包括空格、制表符(水平和垂直)、换行符、回车符等各种类型的空白,比[:blank:]包含的范围广
[:cntrl:] 不可打印的控制字符(退格、删除、警铃...)
[:digit:] 十进制数字
[:xdigit:]十六进制数字
[:graph:] 可打印的非空白字符
[:print:] 可打印字符
[:punct:] 标点符号
\s #匹配任何空白字符,包括空格、制表符、换页符等等。等价于 [\f\r\t\v]。注意 Unicode 正则表达式会匹配全角空格符
\S #匹配任何非空白字符。等价于 [^\f\r\t\v]
\w #匹配一个字母,数字,下划线,汉字,其它国家文字的字符,等价于[_[:alnum:]字]
\W #匹配一个非字母,数字,下划线,汉字,其它国家文字的字符,等价于[^_[:alnum:]字]
范例:
[root@rocky8 data]# ls
aa.txt alpha.log c emp.txt f1.txt.orig fa.txt f.txt pass.txt regex.txt ss2.log test2.txt title.txt
access_log a.txt c.txt f1.txt f2.txt f.patch nianling.txt passwd seq.log test1.txt title1.txt
[root@rocky8 data]# ls |grep 'f..txt'
f1.txt
f1.txt.orig
f2.txt
fa.txt
[root@rocky8 data]# touch faatxt
[root@rocky8 data]# touch fbbtxt
[root@rocky8 data]# ls |grep 'f.\.txt'
f1.txt
f1.txt.orig
f2.txt
fa.txt
#. 表示一个字符 ,要表示f1.txt,就要把后边的. 转义,用f..txt是不行的,要用f.\.txt
[root@rocky8 data]# ls |grep f.\.txt
f1.txt
f1.txt.orig
f2.txt
faatxt
fa.txt
fbbtxt
#正则表达式要用’’ 单引号,引起来,不然使用正则表达式就不生效
#grep 把前面管道传来的结果,当成一个字符串来处理
[root@rocky8 data]# ls f?.txt
f1.txt f2.txt fa.txt
#使用通配符也可以
范例:
[root@rocky8 data]# ls /etc/ | grep 'rc[.0-6]'
rc0.d
rc1.d
rc2.d
rc3.d
rc4.d
rc5.d
rc6.d
rc.d
rc.local
[root@rocky8 data]# ls /etc/ | grep 'rc[.0-6].'
rc0.d
rc1.d
rc2.d
rc3.d
rc4.d
rc5.d
rc6.d
rc.d
rc.local
[root@rocky8 data]# ls /etc/ | grep 'rc[.0-6]\.'
rc0.d
rc1.d
rc2.d
rc3.d
rc4.d
rc5.d
rc6.d
4.1.2 匹配次数
用在要指定次数的字符后面,用于指定前面的字符要出现的次数
* 匹配前面的字符任意次,包括0次,贪婪模式:尽可能长的匹配,如:a* 表示a出现了任意次
.* 任意长度的任意字符
\? 匹配其前面的字符出现0次或1次,即:可有可无
\+ 匹配其前面的字符出现至少1次,即:肯定有且 >=1 次
\{n\} 匹配前面的字符n次,如:a\{10\}
\{m,n\} 匹配前面的字符至少m次,至多n次
\{,n\} 匹配前面的字符至多n次,<=n
\{n,\} 匹配前面的字符至少n次
范例:
[root@rocky8 data]# ls f*
f1.txt f1.txt.orig f2.txt faatxt fa.txt fbbtxt f.patch f.txt
#在通配符中* 星号,表示任意字符串
[root@rocky8 data]# echo aa |grep "a*"
aa
[root@rocky8 data]# echo aaa |grep "a*"
aaa
[root@rocky8 data]# echo aaaaaaa |grep "a*"
aaaaaaa
#在正则表达式里,* 星号表示前面的字符串出现任意次
[root@rocky8 data]# echo b |grep "a*"
b
#出现0次也符合
[root@rocky8 data]# echo b |grep "aa*"
[root@rocky8 data]# echo a |grep "aa*"
a
#表示字符串出现一次或任意次,在前面再加一个字符
[root@rocky8 data]# echo aaaaaaaabbb |grep "aa*"
aaaaaaaabbb
#贪婪模式,直到找到最后一个才不显示,连续的都显示
[root@rocky8 data]# echo a |grep "a\?"
a
[root@rocky8 data]# echo b |grep "a\?"
b
#\? 表示出现0次或1次,可有可无
[root@rocky8 data]# echo aaa |grep "a\?"
aaa
#多次也是满足要求的
[root@rocky8 data]# echo a |grep "a*"
a
[root@rocky8 data]# echo aba |grep "a*"
aba
[root@rocky8 data]# echo aabaa |grep "a*"
aabaa
[root@rocky8 data]# echo aabaa |grep "a\?"
aabaa
[root@rocky8 data]# echo b |grep "a\?"
b
[root@rocky8 data]# echo a |grep "aa\?"
a
[root@rocky8 data]# echo ab |grep "aa\?"
ab
[root@rocky8 data]# echo aba |grep "a\?"
aba
[root@rocky8 data]# echo aba |grep "a*"
aba
#跟a* 类似
#从词意上讲,? 表示1个或0个,* 表示任意个
[root@rocky8 data]# echo aba |grep -o "a\?"
a
a
[root@rocky8 data]# echo aba |grep -o "a*"
a
a
#-o 把匹配的字符串一个个过滤出来,单行打印
[root@rocky8 data]# echo a |grep -o "a\+"
a
[root@rocky8 data]# echo b |grep -o "a\+"
[root@rocky8 data]# echo b |grep "a\+"
#\+ 表示1个以上
[root@rocky8 data]# echo aaaaaaa |grep "a\{7\}"
aaaaaaa
[root@rocky8 data]# echo aaaaaa |grep "a\{7\}"
[root@rocky8 data]# echo aaaaaaaaa |grep "a\{7\}"
aaaaaaaaa
#\{m\} 表示连续的几个字符,少了不行,多了可以
[root@rocky8 data]# echo aaaaaaaaa |grep "a\{7,10\}"
aaaaaaaaa
[root@rocky8 data]# echo aaaaaaaaaaa |grep "a\{7,10\}"
aaaaaaaaaaa
[root@rocky8 data]# echo aaaaaabaaaaa |grep "a\{7,10\}"
#\{m,n\}表示连续的几个到几个字符串,多了可以,少了不行
[root@rocky8 data]# echo aaaaaabaaaaa |grep "a\{,10\}"
aaaaaabaaaaa
#\{,n\}表示小于几个字符
[root@centos8 ~]# echo abc | grep ".*"
abc
#.* 表示任意字符串
[root@rocky8 data]# echo /etc |grep -o '/etc/\?'
/etc
[root@rocky8 data]# echo /etc/ |grep -o '/etc/\?'
/etc/
#表示/etc后边的/斜线,可有可无
[root@rocky8 data]# echo /etc/ |grep -o '/etc/*'
/etc/
[root@rocky8 data]# echo /etc/ |grep -o '/etc/*'
/etc/
[root@rocky8 data]# echo /etc/ |grep -o '/etc/\?'
/etc/
#* 表示任意次,\? 表示可有可无,表示1次或者0次
范例:
[root@rocky8 data]# echo /etc/ |grep "/etc/\?"
/etc/
[root@rocky8 data]# echo /etc |grep "/etc/\?"
/etc
4.1.3 位置锚定
位置锚定可以用于定位出现的位置
^ #行首锚定, 用于模式的最左侧
$ #行尾锚定,用于模式的最右侧
^PATTERN$ #用于模式匹配整行
^$ #空行
^[[:space:]]*$ #空白行
\< 或 \b #词首锚定,用于单词模式的左侧
\> 或 \b #词尾锚定,用于单词模式的右侧
\<PATTERN\> #匹配整个单词
\w #匹配单词构成部分,等价于[_[:alnum:]]
\W #匹配非单词构成部分,等价于[^_[:alnum:]]
#注意: 单词是由字母,数字,下划线组成
范例:
[root@rocky8 data]# grep root /etc/passwd
root:x:0:0:root:/root:/bin/bash
operator:x:11:0:operator:/root:/sbin/nologin
[root@rocky8 data]# grep ^root /etc/passwd
root:x:0:0:root:/root:/bin/bash
#^ 出现在字符串的行首
[root@rocky8 data]# grep 'bash$' /etc/passwd
root:x:0:0:root:/root:/bin/bash
raymond:x:1000:1000::/home/raymond:/bin/bash
boss:x:1001:1001::/home/boss:/bin/bash
#$ 表示以字符串结尾的行
[root@rocky8 data]# grep -v '^$' /etc/init.d/functions
#^$ 表示空行 -v 排除空行
[root@rocky8 data]# cat -A f1.txt
raymond$
$
^I$
$
$
boss$
[root@rocky8 data]# grep -v '^[[:space:]]*$' f1.txt
raymond
boss
#过滤空行、带空格、TAB等的行
[root@rocky8 data]# echo boss | grep '\<boss'
boss
[root@rocky8 data]# echo bossceo | grep '\<boss'
bossceo
[root@rocky8 data]# echo 99bossceo | grep '\<boss'
[root@rocky8 data]# echo 99_bossceo | grep '\<boss'
[root@rocky8 data]# echo 99-bossceo | grep '\<boss'
99-bossceo
#\< 或\b 都表示单词词首
[root@rocky8 data]# echo 99-bossceo | grep 'boss\>'
[root@rocky8 data]# echo 99-boss,ceo | grep 'boss\>'
99-boss,ceo
[root@rocky8 data]# echo 99-boss;ceo | grep 'boss\>'
99-boss
-bash: ceo: command not found
[root@rocky8 data]# echo 99-boss+ceo | grep 'boss\>'
99-boss+ceo
[root@rocky8 data]# echo 99-boss_ceo | grep 'boss\>'
#\> 或\b 表示单词词尾
[root@rocky8 data]# echo 99-boss;ceo | grep 'boss\b'
99-boss
-bash: ceo: command not found
[root@rocky8 data]# echo '99-boss;ceo' | grep 'boss\b'
99-boss;ceo
[root@rocky8 data]# echo "99-boss;ceo" | grep 'boss\b'
99-boss;ceo
#用\b 也可以
范例:排除掉空行和#开头的行
[root@rocky8 data]# grep -v '^$' /etc/profile|grep -v '^#'
[root@rocky8 data]# grep '^[^#]' /etc/profile
4.1.4 分组其它
4.1.4.1 分组
分组:() 将多个字符捆绑在一起,当作一个整体处理,如:(root)+
后向引用:分组括号中的模式匹配到的内容会被正则表达式引擎记录于内部的变量中,这些变量的命名方式为: \1, \2, \3, …
\1 表示从左侧起第一个左括号以及与之匹配右括号之间的模式所匹配到的字符
注意: \0 表示正则表达式匹配的所有字符
示例:
\(string1\(string2\)\)
\1 :string1\(string2\)
\2 :string2
注意: 后向引用引用前面的分组括号中的模式所匹配字符,而非模式本身
范例:
[root@rocky8 data]# echo abcabcabc |grep '\(abc\)\{3\}'
abcabcabc
[root@rocky8 data]# echo abcabc |grep '\(abc\)\{3\}'
#表示连续出现多次,用分组
[root@rocky8 data]# echo abc12345abc |grep '\(abc\).*\1'
abc12345abc
#不连续出现分组,后向引用
[root@rocky8 data]# echo adc12345adc |grep '\(a.c\).*\1'
adc12345adc
[root@rocky8 data]# echo adc12345abc |grep '\(a.c\).*\1'
[root@rocky8 data]# echo adc12345adc |grep '\(a.c\).*\1'
adc12345adc
#a.c 前面出现的是什么 ,后面出现的是什么 ,才可以
[root@rocky8 data]# echo adc12345afedfd123adc |grep '\(a.c\)\(123\).*\2\1'
adc12345afedfd123adc
#第一个分组,后边引用,用\1,表示;第二个分组,后边引用,用\2表示,这就叫后向引用
4.1.4.2 或者
或者:|
示例:
a\|b #a或b
C\|cat #C或cat
\(C\|c\)at #Cat或cat
范例:
[root@rocky8 data]# echo abc | grep 'a\|b12'
abc
[root@rocky8 data]# echo b12 | grep 'a\|b12'
b12
#\| 表示或者, a 或者b12
[root@rocky8 data]# echo b12 | grep '\(a\|b\)12'
b12
[root@rocky8 data]# echo a12 | grep '\(a\|b\)12'
a12
#用分组 表示a12或者b12
范例:排除空行和#开头的行
[root@centos6 ~]#grep -v '^#' /etc/httpd/conf/httpd.conf |grep -v ^$
[root@centos6 ~]#grep -v '^#\|^$' /etc/httpd/conf/httpd.conf
[root@centos6 ~]#grep -v '^\(#\|$\)' /etc/httpd/conf/httpd.conf
[root@centos6 ~]#grep "^[^#]" /etc/httpd/conf/httpd.conf
4.1.5 正则表达式练习
1、显示/proc/meminfo文件中以大小s开头的行(要求:使用两种方法)
2、显示/etc/passwd文件中不以/bin/bash结尾的行
3、显示用户rpc默认的shell程序
4、找出/etc/passwd中的两位或三位数
5、显示CentOS7的/etc/grub2.cfg文件中,至少以一个空白字符开头的且后面有非空白字符的行
6、找出“netstat -tan”命令结果中以LISTEN后跟任意多个空白字符结尾的行
7、显示CentOS7上所有UID小于1000以内的用户名和UID
8、添加用户bash、testbash、basher、sh、nologin(其shell为/sbin/nologin),找出/etc/passwd用户名和shell同名的行
9、利用df和grep,取出磁盘各分区利用率,并从大到小排序
4.2 扩展正则表达式元字符
4.2.1 字符匹配元字符
. 任意单个字符
[wang] 指定范围的字符
[^wang] 不在指定范围的字符
[:alnum:] 字母和数字
[:alpha:] 代表任何英文大小写字符,亦即 A-Z, a-z
[:lower:] 小写字母,示例:[[:lower:]],相当于[a-z]
[:upper:] 大写字母
[:blank:] 空白字符(空格和制表符)
[:space:] 水平和垂直的空白字符(比[:blank:]包含的范围广)
[:cntrl:] 不可打印的控制字符(退格、删除、警铃...)
[:digit:] 十进制数字
[:xdigit:]十六进制数字
[:graph:] 可打印的非空白字符
[:print:] 可打印字符
[:punct:] 标点符号
4.2.2 次数匹配
* 匹配前面字符任意次
? 0或1次
+ 1次或多次
{n} 匹配n次
{m,n} 至少m,至多n次
4.2.3 位置锚定
^ 行首
$ 行尾
\<, \b 语首
\>, \b 语尾
4.2.4 分组其它
() 分组
后向引用:\1, \2, ... 注意:\0 表示正则表达式匹配的所有字符
| 或者
a|b #a或b
C|cat #C或cat
(C|c)at #Cat或cat
范例:
[root@rocky8 data]# echo a12 | grep -E '(a|b)12'
a12
[root@rocky8 data]# echo a12 | egrep '(a|b)12'
a12
#grep -E 或egrep 支持扩展正则表达式
[root@rocky8 data]# ifconfig eth0
eth0: flags=4163<UP,BROADCAST,RUNNING,MULTICAST> mtu 1500
inet 172.31.1.8 netmask 255.255.248.0 broadcast 172.31.7.255
inet6 fe80::20c:29ff:fef9:6ad1 prefixlen 64 scopeid 0x20<link>
ether 00:0c:29:f9:6a:d1 txqueuelen 1000 (Ethernet)
RX packets 11867 bytes 11817539 (11.2 MiB)
RX errors 0 dropped 0 overruns 0 frame 0
TX packets 3942 bytes 700080 (683.6 KiB)
TX errors 0 dropped 0 overruns 0 carrier 0 collisions 0
[root@rocky8 data]# ifconfig eth0 |grep netmask
inet 172.31.1.8 netmask 255.255.248.0 broadcast 172.31.7.255
[root@rocky8 data]# ifconfig eth0 |grep netmask | tr -s " "
inet 172.31.1.8 netmask 255.255.248.0 broadcast 172.31.7.255
[root@rocky8 data]# ifconfig eth0 |grep netmask | tr -s " " |cut -d " " -f3
172.31.1.8
##扩展正则表达式方法
[root@rocky8 data]# ifconfig eth0 |grep netmask | grep -Eo '([0-9]{1,3}\.){3}[0-9]{1,3}' |head -1
172.31.1.8
#正则表达式方法
[root@rocky8 data]# ifconfig eth0 |grep netmask | grep -o '\([0-9]\{1,3\}\.\)\{3\}[0-9]\{1,3\}' |head -1
172.31.1.8
4.2.5 扩展正则表达式练习
1、显示三个用户root、raymond、boss的UID和默认shell
2、找出/etc/rc.d/init.d/functions文件中行首为某单词(包括下划线)后面跟一个小括号的行
3、使用egrep取出/etc/rc.d/init.d/functions中其基名
4、使用egrep取出上面路径的目录名
5、统计last命令中以root登录的每个主机IP地址登录次数
6、利用扩展正则表达式分别表示0-9、10-99、100-199、200-249、250-255
7、显示ifconfig命令结果中所有IPv4地址
8、将此字符串:welcome to rocky linux 中的每个字符去重并排序,重复次数多的排到前面