文本编辑三剑客之grep
文本处理工具:
- Linux上文本处理三剑客
- grep:文本过滤工具(模式: pattern)工具:
- sed: stream editor,流编辑器:文本编辑工具;
- awk: Linux上的实现为gawk,文本报告生成器(格式化文本);
正则表达式: Regual Expression, REGEXP
由一类特殊字符及文本字符所编写的模式,其中有些字符不表示其字面意义,而是用于表示控制或通配的功能;
分两类:;
基本正则表达式: BRE
扩展正则表达式: ERE
元字符: (hellottspace:J)+)+
grep: Global search REgular expression and Print out the line
作用:文本搜索工具,根据用户指定的“模式(过滤条件)”对目标文本逐行进行匹配检查;打印匹配到的行;
模式:由正则表达式的元字符及文本字符所编写出的过滤条件;
正则表达式引擎;
- grep [OPTIONS] PATTERN [FILE…]
- grep [OPTIONS] [e PATTERN -f FILE] [FILE…]
- OPTIONS:
-color=auto:对匹配到的文本着色后高亮显示;
-i: ignorecase,忽略字符的大小写;
-o:仅显示匹配到的字符串本身;
-v:–Invert-match-:显示不能被模式匹配到的行;
-E:支持使用扩展的正则表达式元字符;
-q:quiet,–silent:静默模式,即不输出任何信息;
-A #: after,后#行
-B #: before,前#行
-C #: context,前后各#行
- OPTIONS:
–color:对匹配到的文本着色后高亮显示
grep “UUID” --color=auto /etc/fstab
-i:忽略字符大小写
grep -i “uuid” --color /etc/fstab
duan@duan-PC:~$ grep -i "uuid" --color /etc/fstab
UUID=b43491a6-b3a4-42a4-9d10-001e4d2ea3e9 / ext4 rw,relatime 0 1
UUID=8b1d321e-eb2b-4473-bd27-9479223026d4 /boot ext4 rw,relatime 0 2
UUID=588354cb-96ed-4499-b7d5-bec7b34c3ec6 /data ext4 rw,relatime 0 2
UUID=e44f0306-6e81-4669-83f9-fc91250d6066 /recovery ext4 rw,relatime 0 2
UUID=6cd0312f-3887-446a-bf77-c2d6eb450bfe none swap defaults,pri=-2 0 0
duan@duan-PC:~$
-o:仅显示匹配到的字符串本身
grep -o “UUID” --color /etc/fstab
duan@duan-PC:~$ grep -o "UUID" --color /etc/fstab
UUID
UUID
UUID
UUID
UUID
duan@duan-PC:~$
-v:显示不能被命令匹配到的行
grep -v “UUID” /etc/fstab (即选项是什么不显示什么)
duan@duan-PC:~$ grep -v "UUID" /etc/fstab
# /dev/sda5
# /dev/sda1
# /dev/sda7
# /dev/sda3
# /dev/sda4
/data/home /home none defaults,bind 0 0
/data/opt /opt none defaults,bind 0 0
/data/root /root none defaults,bind 0 0
/data/var /var none defaults,bind 0 0
duan@duan-PC:~$
-q:静默模式,不输出任何信息
grep -q “UUID” --color /etc/fstab
duan@duan-PC:~$ grep -q "UUID" --color /etc/fstab
duan@duan-PC:~$ echo $?
0
duan@duan-PC:~$ grep -q "UUuiID" --color /etc/fstab
duan@duan-PC:~$ echo $?
1
duan@duan-PC:~$
0代表匹配到了,1代表没有匹配到,grep到的结果可以当作一种判断条件
-A#:after,显示匹配到的后#行
grep -A 2 --color “root” /etc/passwd(显示/etc/passwd文件中带有root行的后两行)
duan@duan-PC:~$ grep -A 2 --color "root" /etc/passwd
root:x:0:0:root:/root:/bin/bash
daemon:x:1:1:daemon:/usr/sbin:/usr/sbin/nologin
bin:x:2:2:bin:/bin:/usr/sbin/nologin
--
nm-openvpn:x:111:117:NetworkManager OpenVPN,,,:/var/lib/openvpn/chroot:/usr/sbin/nologin
nm-openconnect:x:112:118:NetworkManager OpenConnect plugin,,,:/var/lib/NetworkManager:/usr/sbin/nologin
pulse:x:113:120:PulseAudio daemon,,,:/var/run/pulse:/usr/sbin/nologin
duan@duan-PC:~$
-B#:before,前#行
grep -B 2 --color “root” /etc/passwd (显示/etc/passwd文件中带有root行的前两行,可以看出第一个root是文件中的第一行,所以不显示)
duan@duan-PC:~$ grep -B 2 --color "root" /etc/passwd
root:x:0:0:root:/root:/bin/bash
--
sshd:x:110:65534::/run/sshd:/usr/sbin/nologin
deepin-anything-server:x:999:999::/home/deepin-anything-server:/sbin/nologin
nm-openvpn:x:111:117:NetworkManager OpenVPN,,,:/var/lib/openvpn/chroot:/usr/sbin/nologin
duan@duan-PC:~$
-C#:context,前后各#行
grep -C 2 --color “root” /etc/passwd (显示/etc/passwd文件中带有root行的前后各两行,第一个root是文件中的第一行,所以不显示前面的)
duan@duan-PC:~$ grep -C 2 --color "root" /etc/passwd
root:x:0:0:root:/root:/bin/bash
daemon:x:1:1:daemon:/usr/sbin:/usr/sbin/nologin
bin:x:2:2:bin:/bin:/usr/sbin/nologin
--
sshd:x:110:65534::/run/sshd:/usr/sbin/nologin
deepin-anything-server:x:999:999::/home/deepin-anything-server:/sbin/nologin
nm-openvpn:x:111:117:NetworkManager OpenVPN,,,:/var/lib/openvpn/chroot:/usr/sbin/nologin
nm-openconnect:x:112:118:NetworkManager OpenConnect plugin,,,:/var/lib/NetworkManager:/usr/sbin/nologin
pulse:x:113:120:PulseAudio daemon,,,:/var/run/pulse:/usr/sbin/nologin
duan@duan-PC:~$
基本正则表达式元字符:
- :字符匹配:
- .:匹配任意单个字符;
- []:匹配指定范围内的任意单个字符;
- [^] :匹配指定范围外的任意单个字符;
[digit]、[lower:]、[:upper、[alpha:]、[alnum:、[punct:]、[space:]
- 匹配次数:用在要指定其出现的次数的字符的后面,用于限制其前面字符出现的次数;默认工作于贪婪模式;
* :匹配其前面的字符任意次; 0,1,多次;
例如: grep “x*y”
abxy
aby
xxxxxxy
yab
这些字符都会被匹配到,不管x出现几次,把带y字符的行显示出来,x可有可无
.*: 匹配任意长度的任意字符
例如:
duan@duan-PC:~$ grep "e.*t" /etc/fstab
UUID=b43491a6-b3a4-42a4-9d10-001e4d2ea3e9 / ext4 rw,relatime 0 1
UUID=8b1d321e-eb2b-4473-bd27-9479223026d4 /boot ext4 rw,relatime 0 2
UUID=588354cb-96ed-4499-b7d5-bec7b34c3ec6 /data ext4 rw,relatime 0 2
UUID=e44f0306-6e81-4669-83f9-fc91250d6066 /recovery ext4 rw,relatime 0 2
UUID=6cd0312f-3887-446a-bf77-c2d6eb450bfe none swap defaults,pri=-2 0 0
/data/home /home none defaults,bind 0 0
/data/opt /opt none defaults,bind 0 0
/data/root /root none defaults,bind 0 0
/data/var /var none defaults,bind 0 0
匹配e和t中间的任意字符
\?: 匹配其前面的字符0次或1次;即前面的字符是可有可无的;
例如:
duan@duan-PC:~$ grep "e\?t" /etc/fstab
UUID=b43491a6-b3a4-42a4-9d10-001e4d2ea3e9 / ext4 rw,relatime 0 1
UUID=8b1d321e-eb2b-4473-bd27-9479223026d4 /boot ext4 rw,relatime 0 2
UUID=588354cb-96ed-4499-b7d5-bec7b34c3ec6 /data ext4 rw,relatime 0 2
UUID=e44f0306-6e81-4669-83f9-fc91250d6066 /recovery ext4 rw,relatime 0 2
UUID=6cd0312f-3887-446a-bf77-c2d6eb450bfe none swap defaults,pri=-2 0 0
/data/home /home none defaults,bind 0 0
/data/opt /opt none defaults,bind 0 0
/data/root /root none defaults,bind 0 0
/data/var /var none defaults,bind 0 0
duan@duan-PC:~$
匹配et的字符,e是可有可无的,
\+:匹配其前面的字符1次或多次;即其面的字符要出现至少1次;
grep "e\+t" /etc/fstab
匹配et的字符,e最少出现一次
\{m\}:匹配其前面的字符m次;(m换成要匹配的次数,精确匹配);
grep "e\{1\}t" /etc/fstab
匹配et的字符,前面出现一此e的字符
\{m,n\}:匹配其前面的字符至少m次,至多n次;
grep "e\{2,5\}t" /etc/fstab
匹配et的字符 e最少出现两次,最多出现5次
\{0,n\}:至多n次
grep "e\{0,5\}t" /etc/fstab
匹配et的字符,e最多出现5次
\{m,\}:至少m次
grep "e\{2,\}t" /etc/fstab
匹配et的字符,e最少出现2次
- 位置锚定:
- ^:行首锚定;用于模式的最左侧;
- $ :行尾锚定;用于模式的最右侧;
- ^APATTERN$:用于PATTERN来匹配整行;
- ^$ :空白行;
- ^ [[:space:]]*$:空行或包含空白字符的行;
单词:非特殊字符组成的连续字符(字符串)都称为单词;
<或\b:词首锚定,用于单词模式的左侧;
>或\b:词尾锚定,用于单词模式的右侧;
< PATTERN>:匹配完整单词;
^:行首锚定;用于模式的最左侧;
grep “^root” /etc/passwd
duan@duan-PC:~$ grep "root" /etc/passwd
root:x:0:0:root:/root:/bin/bash
nm-openvpn:x:111:117:NetworkManager OpenVPN,,,:/var/lib/openvpn/chroot:/usr/sbin/nologin
chroot:x:1001:1001::/home/chroot:/bin/chroot
duan@duan-PC:~$ grep "^root" /etc/passwd
root:x:0:0:root:/root:/bin/bash
过滤只出现在行首的root行
$:行尾锚定;用于模式的最右侧;
grep “root$” /etc/passwd
duan@duan-PC:~$ grep "root$" /etc/passwd
chroot:x:1001:1001::/home/chroot:/bin/chroot
duan@duan-PC:~$
过滤只出现在行尾的root行
^APATTERN$:用于PATTERN来匹配整行;
grep “^root$” /etc/passwd
duan@duan-PC:~$ grep "^root$" /etc/passwd
root
duan@duan-PC:~$
匹配只有root的行,有别的字符都匹配不到,用来匹配整行
\<或\b:词首锚定,用于单词模式的左侧;
grep “<root” /etc/passwd
duan@duan-PC:~$ grep "\<root" /etc/passwd
root:x:0:0:root:/root:/bin/bash
root
duan@duan-PC:~$
匹配单词,用于匹配词首,过滤出词首为root的单词
\>或\b:词尾锚定,用于单词模式的右侧;
grep “root>” /etc/passwd
duan@duan-PC:~$ grep "root\>" /etc/passwd
root:x:0:0:root:/root:/bin/bash
nm-openvpn:x:111:117:NetworkManager OpenVPN,,,:/var/lib/openvpn/chroot:/usr/sbin/nologin
chroot:x:1001:1001::/home/chroot:/bin/chroot
root
duan@duan-PC:~$
匹配单词,用于匹配词尾,过滤出词尾为root的单词
\< PATTERN\>:匹配完整单词;
grep “<root>” /etc/passwd
duan@duan-PC:~$ grep "\<root\>" /etc/passwd
root:x:0:0:root:/root:/bin/bash
root
duan@duan-PC:~$
精确锚定单词,匹配root单词;
练习:
1、显示/etc/passwd文件中不以/bin/bash结尾的行;
grep -v "/bin/bash$" /etc/passwd
2、找出/etc/ passwd文件中的两位数或三位数;
grep "\<[0-9]\{2,3\}\>" /etc/passwd
3、找出etc/ rc. d/ro, sysinit或/ etc/grub2cg文件中,以至少一个距白字符开头,且后面非空白字符的行
grep "^[[:space:]]\+[^[:space:]]" /etc/grub2.cfg
4、找出" netstat-tan"命令的结果中以 LISTEN后跟0、1或多个空白字符结尾的行
netstat -ant | grep "LISTEN[[:space:]]*$"
分组及引用
xy*ab 表示y可以出现0次一次或多次,和x没关系
可以把xy用()捆绑在一起,当作一个整体进行处理
\(\):将一个或多个字符捆绑在一起,当作一个整理来处理,bash shell中的括号是有特殊意义的,需要用\转义符,把括号转义为括号来使用,不加括号的话命令行会把括号来进行解释,不懂的话理解为必须加\就行了
Note:分组括号中的模式匹配到的内容会被正则表达式引擎自动记录于内部的变量中,这些变量为
\1:模式从左侧起,第一个左括号以及与之匹配的右括号之间的模式所匹配到的字符;
\2:模式从左侧起,第二个左括号以及与之匹配的右括号之间的模式所匹配到的字符;
\3
…
He loves his lover.
He likes his lover.
She likes her liker.
She loves her liker.
duan@duan-PC:~$ grep "l..e.*l..e" 1.txt
He loves his lover.
He likes his lover.
She likes her liker.
She loves her liker.
duan@duan-PC:~$ grep "\(l..e\).*\1" 1.txt
He loves his lover.
She likes her liker.
duan@duan-PC:~$
可以看出不加括号就会匹配中间不同的单词,想要匹配相同的就需要加括号,\1就是调用第一个左括号以及与之匹配的右括号中的内容,\2就是调用第二个左括号
egrep:
支持扩展的正则表达式实现类似于grep文本过滤功能; grep-E
egrep [OPTIONS] PATTERN [FILE.]
选项:
-o,v,-q,A-B,C(和grep用法一样)
-G:支持基本正则表达式(加了-G和grep一样)
扩展正则表达式的元字符:
字符匹配(和grep用法一样)
.:任意单个字符
[]:指定范围内的任意单个字符
[^]:指定范围外的任意单个字符
次数匹配(不需要\来进行转义)
*:任意次,0,1或多次
?:0次或1次,其前的字符是可有可无的;
+:其前字符至少1次
{m}:其前的字符m次;
{m,n}:至少m次,至多n次;
{0,n}:至多n次;
{m,}:至少m次;
位置锚定(和grep用法一样)
^:行首锚定;
$:行尾锚定;
\<,\b:词首锚定;
\>,\b:词尾锚定;
分组及引用:(和grep用法一样)
():分组;括号内的模式匹配到的字符会被记录于正则表达式引擎的内部变量中;
后向引用:\1,\2, …
a|b:a或者b;
(C|c)at:Cat或cat
C|cat:C或cat
练习:
1、找出/ proc/meminfo文件中,所有在大写或小写s开头的行;至少有三种实现方式;
duan@duan-PC:~$ grep -i "^s" /proc/meminfo
duan@duan-PC:~$ grep -i "^[sS]" /proc/meminfo
duan@duan-PC:~$ egrep "^(s|S)" /proc/meminfo
2、显示当前系统上root、centos或user1用户的相关信息;
duan@duan-PC:~$ grep -E "^(root|centos|user1)\>" /etc/passwd
3、使用echo命令输出一绝对路径,使用 egrep取出基名;
echo /etc/xx/ |grep -E -o "[^/]+?/$"
[^/]的意思是非/这个符号,把/除外
4、找出ifconfig命令结果中的1-255之间的数值;
ifconfig | grep -E -o "\<([1-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])"
锚定词首:一位数1-9,二位数1-9、0-9,三位数的第一位为1、第二位0-9、出现两次,又一遍三位数的第一位是2第二位是0-4、第三位是0-9,又一遍三位数的前两位是25、第三位0-5
6、课外作业:找出ifconfigs命令结果中的IP地址;
6、添加用户bash,nologin,设置shell与用户名相同,而后找出/etc/ passwd文件中用户名同shell名的行;
grep -E "(^[^:]+\>).*\1$" /etc/passwd
利用分组,^:锚定行首;
[^:]:因为:是当分隔符的,把:除外就可以锚定到行首;
+\>:加锚定词尾,然后用()把锚定的单词括起来
.*:匹配所有单词
\1$:引用一下前面的分组,然后锚定行尾
fgrep:不支持正则表达式元字符;
当无需用到元字符去编写模式时,使用fgrep必能更好