系统帮助:
grep, egrep, fgrep - print lines matching a pattern
grep: Global Research Regular Expression, 根据模式搜索文本,并将符合模式的文本行显示出来。
Pattern: 模式, 文本字符和正则表达式的元字符组合而成匹配条件
模式中,如果没有元字符,可以不用引号(单双)括起来。
正则表达式的元字符? 详见下面.
grep的格式: 使用基本正则表达式定义的模式来过滤文本的命令;
grep [options] PATTERN [FILE...]
grep:使用基本正则表达式定义的模式来过滤文本的命令;
-i: 忽略大小写
-v: 取反, 显示没有被模式匹配到的行
-o: 仅显示匹配的字符串, 每个字符串显示为一行,用于寻找匹配次数,与wc可以一起用。
--color|--colour: 高亮颜色显示匹配的字符串.
-E: 使用扩展正则表达式
-A #: After, #指定显示的行数, 表示匹配到行以后, 一并显示其后面的两行; 各匹配结果之间, 以"--"上下分割; 注: 必须要指定行数#
-B #: Before, 一并显示其前的#行.
-C #: Context, 一并显示上下#行.
Exp:
# grep 'root' /etc/passwd
root:x:0:0:Liemer,Beijing,110,119:/root:/bin/bash
operator:x:11:0:operator:/root:/sbin/nologin
grep中用到的引号, 只要不涉及变量, 单双引号都是可以的; 如果不涉及元字符, 引号甚至是可以省略的.
shell中的特殊字符的含义: (注意,与元字符的含义不同)
*: 任意长度的任意字符
?: 任意单个字符
[]: 指定范围内
[^]: 指定范围外
正则表达式:REGular EXPression, REGEXP
元字符:表示通配或更加复杂意义功能的字符. 元字符仅修饰其前字符.
1. .: 匹配任意单个字符
# grep 'r..t' /etc/passwd
root:x:0:0:Liemer,Beijing,110,119:/root:/bin/bash
operator:x:11:0:operator:/root:/sbin/nologin
ftp:x:14:50:FTP User:/var/ftp:/sbin/nologin
2. []: 匹配指定范围内的任意单个字符(和bash一样)
3. [^]:匹配指定范围外的任意单个字符(和bash一样)
字符集合:[:digit:], [:lower:], [:upper:], [:punct:], [:space:], [:alpha:], [:alnum:]
表示: 数字, 小写字母, 大写字母, 标点, 空白字符, 所有大小写字母, 大小写字母和数字.
上面的只是字符集合, 实际运用中, 还需要在外层包裹一个中括号[].
# grep '[[:alnum:]]$' b.txt //过滤以大小写字母和数字结尾的行
# grep '[[:space:]][[:alnum:]]$' b.txt //过滤以一个空白字符紧跟一个大小写字母或数字结尾的行.
4. 表示匹配次数(贪婪模式: 默认的正则表达式的匹配模式, 尽量最长地匹配):
*: 匹配其前面的字符任意次,这里就与shell中表示的的意思不一样了
.*: 任意长度的任意字符
5. \?: 匹配其前字符0次或者1次,同样需要转义,bash中的?表示任意单个字符
6. \{m,n\}: 匹配其前面的字符至少m次,至多n次; 转义是防止shell解释{}为命令行展开(# touch ~/{a,b}.txt; $ ls ~ --> a.txt b.txt);
\{1,\}: 至少一次, 多了不限.
\{0,3\}: 最多三次, 少了不限.
\: 转义字符的意思, 就是防止按照shell的格式来解释相关的字符, 而是用正则的方法来实现.
例子:
Exp: 新建文本, 输入如下内容, 一段字符串一行.
a, b, ab, aab, acb, adb, amnb
1)匹配a任意次, 后面跟一个b的字符串:
a*b: a出现任意次, 后面跟一个b;
# grep 'a*b' a.txt
b
ab
aab
acb
adb
amnb
2)匹配a可有可无, 后面跟一个b的字符串: a?b: a出现1次或者0次. 注: 要用\来转意.
# grep 'a\?b' a.txt
b
ab
aab
acb
adb
amnb
3)匹配a开头, b结尾, 中间任意长度任意字符的字符串. a.*b: 贪婪匹配, a开头, b结尾, 中间任意字符.
# grep 'a.*b' a.txt
ab
aab
acb
adb
amnb
4)匹配a至少一次, 至多三次, 后面跟一个b的行:
# grep 'a\{1,3\}b' a.txt
ab
aab
5)统计/etc/inittab中空白行的数量.
# grep '^$' /etc/inittab |wc -l
5
7. 位置锚定:
^: 锚定行首,此字符后面的任意内容必须出现在行首
$: 锚定行尾,此字符前面的任意内容必须出现在行尾
^$: 空白行
Exp:
1)行首锚定.
# grep '^r..t' /etc/passwd
root:x:0:0:Liemer,Beijing,110,119:/root:/bin/bash
2)行尾锚定.
# grep '/bin/bash$' /etc/passwd
root:x:0:0:Liemer,Beijing,110,119:/root:/bin/bash
cactiuser:x:505:505::/home/cactiuser:/bin/bash
lius:x:506:506::/home/lius:/bin/bash
apache:x:498:498::/home/apache:/bin/bash
openstack:x:509:509::/home/openstack:/bin/bash
hive:x:5000:5000:Hive:/home/hive:/bin/bash
8. 单词锚定
\<或\b: 锚定词首,其后面的任意字符必须作为单词首部出现
\>或\b: 锚定词尾,其前面的任意字符必须作为单词的尾部出现
# grep '\<root' /etc/passwd //过滤root作为词首的行
# grep 'root\>' /etc/passwd //过滤root作为词尾的行
# grep '\<root\>' /etc/passwd //过滤含有root单词的行,必须是单词。
Exp: 编写文档:
This is root.
The user is mroot.
rooter is a dog's name.
chroot is a command.
mrooter is not a word.
1) 查找以root做为词尾的行.
[root@lius]<~># grep 'root\>' a.txt 或 grep 'root\b' a.txt
This is root.
The user is mroot.
chroot is a command.
2) 查找以root做为词首的行.
[root@lius]<~># grep '\<root' a.txt 或 grep '\broot' a.txt
This is root.
rooter is a dog's name.
3) 查找含有root单词的行.
[root@lius]<~># grep '\broot\b' a.txt
This is root.
[root@lius]<~># grep '\<root\>' a.txt
9. 分组:
\(\): 分组, 将()里面的内容当做一个整体来处理.
分组的意义: 分组一般用于引用, 即: 后向引用.
\(ab\)*: 匹配ab出现任意次的字符串.
后向引用: 即分组后的内容, 后面一般会有相应的元字符对其进行引用.
\1: 引用第一个左括号以及与之对应的右括号所包括的所有内容(注意:括号是可以嵌套的)
\2: 引用第二个左括号以及与之对应的右括号所包括的所有内容
\3: 引用第三个左括号以及与之对应的右括号所包括的所有内容
Exp:过滤一行中, 前面有一个单次, 后面也有包含这个单词内容的行.
He love his lover.
She like her liker.
He like his lover.
she love her liker.
1)匹配前面一段代码, 后面出现相同一段代码的行.
# grep 'l..e.*l..e' a.txt
He love his lover.
She like her liker.
He like his lover.
she love her liker.
可见, 上面的匹配格式, 不能满足我们的需求.
后向引用:
# grep '\(l..e\).*\1' a.txt //l..e可以匹配love和like, \1表示引用的变量编号.
He love his lover.
She like her liker.
后面出现前面第一个括号里面的内容的行, 才能过滤出.
2)引用多个变量呢? 文本中添加一行:
she loves her liker. He loves his liker.
引用两个变量:
# grep '\(l.v\).*\(l.k\).*\1.*\2' a.txt
she loves her liker. He loves his liker.
这里有颜色显示的部分是: loves her liker. He loves his lik, 引用的结果是准确的.
3)过滤/etc/inittab中, 出现一个数字, 中间任意字符, 但以这个数字结尾的行:
# grep '\([[:digit:]]\).*\1' /etc/inittab
练习题:
1、显示/proc/meminfo文件中以不区分大小的s开头的行;
grep -i '^s' /proc/meminfo
grep '^[sS]' /proc/meminfo
2、显示/etc/passwd中以nologin结尾的行;
grep 'nologin$' /etc/passwd
取出默认shell为/sbin/nologin的用户列表
grep "nologin$' /etc/passwd | cut -d: -f1
取出默认shell为bash,且其用户ID号最小的用户的用户名
grep 'bash$' /etc/passwd | sort -n -t: -k3 | head -1 | cut -d: -f1
3、显示/etc/inittab中以#开头,且后面跟一个或多个空白字符,而后又跟了任意非空白字符的行;
grep "^#[[:space:]]\{1,\}[^[:space:]]" /etc/inittab
4、显示/etc/inittab中包含了:一个数字:(即两个冒号中间一个数字)的行;
grep ':[0-9]:' /etc/inittab
5、显示/boot/grub/grub.conf文件中以一个或多个空白字符开头的行;
grep '^[[:space:]]\{1,\}' /boot/grub/grub.conf
6、显示/etc/inittab文件中以一个数字开头并以一个与开头数字相同的数字结尾的行;
grep '^\([0-9]\).*\1$' /etc/inittab
7、找出某文件中的,1位数,或2位数;
grep '[0-9]\{1,2\}' /proc/cpuinfo
grep --color '\<[0-9]\{1,2\}\>' /proc/cpuinfo
8、找出ifconfig命令结果中的1-255之间的整数;
9、查找当前系统上名字为student(必须出现在行首)的用户的帐号的相关信息, 文件为/etc/passwd
grep '^student\>' /etc/passwd | cut -d: -f3
id -u student
student1
student2
10、分析/etc/inittab文件中如下文本中前两行的特征(每一行中出现在数字必须相同),请写出可以精确找到类似两行的模式:
l1:1:wait:/etc/rc.d/rc 1
l3:3:wait:/etc/rc.d/rc 3
grep '^l\([0-9]\):\1.*\1$' /etc/inittab
正则表达式:REGEXP, REGular EXPression,分为基本正则表达式(Basic)和扩展正则表达式(Extended)
grep的扩展正则表达式: 不用脱义\
grep -E = egrep
字符匹配:以下三种, 扩展和基本用法相同, 没有需要脱义的符号.
.:任意单个字符
[]:范围内的任意单个字符
[^]:范围外的任意单个字符
次数匹配中:?|{}不用再脱义, 另外多了一个+.
*: 其前自
?: 其前字符0次或者1次.
+: 匹配其前面的字符至少1次, 相当于\{1,\}
{m,n}: 指定范围, 不用再脱义.
位置锚定:和非扩展的用法完全相同
^: 行首
$:行尾
\<, \b:词首
\>, \b:词尾
分组:用法不同, ()不再用脱义
():分组
\1, \2, \3, ...
同时, 还扩展了一个字符|, 表示或者.
|: or, 或者.
C|cat: 不是指Cat或cat, 而是C或cat; 也就是说, |左右的两个字段是或者的关系, 而不是只匹配左右的前后两个字符.
如果要表示前者的意思, 分组就显现出作用了, 应该是(C|c)at.
扩展示例:
1)找出/boot/grub/grub.conf文件中1-255之间的数字;
egrep --color \<([1-9]|[1-9][0-9]|1[0-9][0-9]|2[0-4][0-9]|25[0-5])\> /boot/grub/grub.conf
egrep --color '\<[0-9]\>|\<[1-9][0-9]\>|\<1[0-9][0-9]\>|\<2[0-4][0-9]\>|\<25[0-5]\>' /boot/grub/grub.conf
这里, 用括号分组, 则锚定词首词尾的时候是将一个整体全部锚定; 如果不加括号, 则|符号之后的并不能锚定, 大于255的数值也会被过滤出来.
2)ifconfig -a的内容, 保存到c.txt中, 过滤ip地址类的行.
注: \. --> 对 "." 进行脱义, 非元字符., 可以代表任意一个字符, 如可以过滤出192*168.213.55
ifconfig -a > c.txt
egrep --color '\<([0-9]|[1-9][0-9]|1[0-9][0-9]|2[0-4][0-9]|25[0-5])\>\.\<([0-9]|[1-9][0-9]|1[0-9][0-9]|2[0-4][0-9]|25[0-5])\>\.\<([0-9]|[1-9][0-9]|1[0-9][0-9]|2[0-4][0-9]|25[0-5])\>\.\<([0-9]|[1-9][0-9]|1[0-9][0-9]|2[0-4][0-9]|25[0-5])\>' c.txt
这里, 必须对([0-9]|[1-9][0-9]|1[0-9][0-9]|2[0-4][0-9]|25[0-5])进行分组, 否则过滤的数字会超出范围.
ifconfig | egrep '\<([0-9]|[1-9][0-9]|1[0-9][0-9]|2[0-4][0-9]|25[0-5])\>\.\<([0-9]|[1-9][0-9]|1[0-9][0-9]|2[0-4][0-9]|25[0-5])\>\.\<([0-9]|[1-9][0-9]|1[0-9][0-9]|2[0-4][0-9]|25[0-5])\>\.\<([0-9]|[1-9][0-9]|1[0-9][0-9]|2[0-4][0-9]|25[0-5])\>'
ifconfig | egrep --color '(\<([0-9]|[1-9][0-9]|1[0-9][0-9]|2[0-4][0-9]|25[0-5])\>\.){3}\<([0-9]|[1-9][0-9]|1[0-9][0-9] |2[0-4][0-9]|25[0-5])\>'
IPV4的分类:
IPv4: 一共5分类, 以首位的区间为分类标准.
5类:A B C D E, 有用的只有三类.
A:1-127
B:128-191
C:192-223
IP地址的过滤规则:第一位的范围【1-223】,每一位的最大值不能是255,
\<([1-9]|[1-9][0-9]|1[0-9]{2}|2[01][0-9]|22[0-3])\>(\.\<([0-9]|[1-9][0-9]|1[0-9][0-9]|2[0-4][0-9]|25[0-4])\>){2}\.\<([1-9]|[1-9][0-9]|1[0-9][0-9]|2[0-4][0-9]|25[0-4])\>
马哥的博客:http://mageedu.blog.51cto.com/
grep, egrep:默认的grep是非常浪费cpu的时钟周期的。
fgrep: fast grep, 任何正则表达式的字符, 都当做普通字符来显示. 不支持正则表达式, 所以执行速度快.
# echo -e "r..t\nroot" > a.txt
# grep 'r..t' a.txt
r..t
root
# fgrep --color 'r..t' a.txt
r..t
转载请注明:liutianfeng.com » grep-egrep-fgrep家族
发表回复
要发表评论,您必须先登录。