grep是linux上常用的一个文本处理工具之一。它有着强大的文本处理能力,学会它,可以让工作更有效率。
一、初识grep
grep: Global search Regular Experssion and Print out line
从名字上也可以直观的了解到它是基于正则表达式进行全局搜索,并把结果打印到屏幕上来。
说白了,它就是根据用户指定的“模式(pattern)”来对文本进行过滤,并显示匹配到的行的文本搜索工具。
二、何为“模式”
所谓模式,就是由一类字符书写,但是这些字符不表示字符本身字面的意义,而是表示控制或通配的功能。它还有一个高雅的名字,即正则表达式。
三、了解正则表达式
1、基本的元字符
. 匹配任意的字符
* 匹配其前面的字符任意次数,0,1或多次
\? 匹配其前面的字符0次或1次
\+ 匹配其前面的字符1次以上
2、按字符匹配:
.: 匹配任意单个字符
[]: 匹配指定集合中的任意单个字符
常用的字符集合:
[[:digit:]],[0-9] 表示0-9的任意数字
[[:lower:]], [a-z] 表示26个小写英文字母
[[:upper:]], [A-Z] 表示26个大写英文字母
[[:alpha:]], [a-zA-Z] 表示所有英文字母
[[:alnum:]], [[0-9a-zA-Z] 表示数字,所有英文字母
[[:space:]] 表示空白字符
[[:punct:]] 表示符号字符
[^]: 匹配指定集合外的任意单个字符
3、按匹配次数匹配:
* : 匹配其前面任意字符任意次数
\?: 匹配其前面的字符0次或1次
\+: 匹配其前面的字符出现至少1次
\{m\}: 匹配其前面的字符出现m次
\{m,n\}: 匹配其前面的字符至少m次,至多n次
.* : 常用组合,表示任意长度的任意字符
4、实现位置锚定
^ : 写在模式的最左侧,表示锚定行首
$ : 写在模式的最右侧,表示锚定行尾
\<: 写在要查找的单词模式的左侧,做单词词首锚定
\>: 写在要查找的单词模式的右侧,做单词词尾锚定
^$: 常用组合,表示空白行
\<pattern\>: 匹配单词
5、实现分组(只要功能可以用于实现后向引用)
\(\): 在模式中,如果使用了分组,在某行文本检测中,如果\(\)匹配到了某内容,此内容可以在后面的模式中被引用。
\# : 引用之前被\(\)所匹配到的内容,模式自左而右,引用第#个左括号以及其匹配右括号之间的模式匹配到的内容。
三、grep命令
1、基本语法:
grep [OPTIONS] PATTERN [FILE…]
常用选项:
-i, –ignore-case : 忽略字符大小写
-o, –only-matching : 只显示被模式匹配到的内容
-v, –invert-match : 反向选取,显示被模式匹配到的内容的相反内容
-A #,–after-context=#: 显示被模式匹配到的行和此行之后的#行
-B #,–before-context=#: 显示被模式匹配到的行和此行之前的#行
-C #,–context=#: 显示被模式匹配到的行和此行前后的#行
-r, -R, –recursive: 递归查询,对目录下的子目录也会进行查询
-E, –extended-regexp: 使用扩展正则表达式进行匹配,相当于egrep
-F, –fixed-strings: 不使用正则表达式经行匹配,即忽略元字符的意义,相当于fgrep
–color={never,always,auto}:可以设置颜色显示,可以进行别名,方便使用。例如:alias grep='grep –color=auto'
四、知识点练习
接下来我们以以下文本文件的内容来进行练习
练习1:显示b出现3次以上的行
grep "b\{3,\}" test.txt
练习2:统计文本文件中work|WORK出现的次数
grep -i -o "\<work\>" test.txt | wc -l
练习3:显示所有包含符号的行
grep "[[:punct:]]" test.txt
练习4:找出其中最后一个单词是由此前某单词加er构成的行。
grep "\(\<[[:alpha:]]\+\>\).*\1er" test.txt
五、实际的应用
有了以上的知识储备,我们就可以用grep来进行一些基本的处理工作了。
1、在/etc/passwd上查找以/sbin/nolog结尾的行,即可以使用以/bin/nologin为结束的位置锚定进行选取
grep "/sbin/nologin$" /etc/passwd
2、在/etc/passwd上查找用户id和组id在500到1099之间的行
grep "\<1\?[05][0-9][0-9]\>" /etc/passwd
3、查找当前系统上网卡驱动程序的名称
#显示pci设备中网卡的信息 #最前面的 “02:01.0” 就是设备在PCI总线上的代号,该代号在整个系统中是唯一的。(因为当前系统上有两块网卡,所以有两条信息) [root@localhost tmp]# lspci | grep "Ethernet" 02:01.0 Ethernet controller: Intel Corporation 82545EM Gigabit Ethernet Controller (Copper) (rev 01) 02:05.0 Ethernet controller: Intel Corporation 82545EM Gigabit Ethernet Controller (Copper) (rev 01) #sys目录是内核将设备信息映射出来的一个伪文件系统,所以我们查找到的那一行信息中drivers的子目录e1000即是网卡设备的驱动名称 [root@localhost tmp]# find /sys/bus/pci/drivers | grep "02:01.0" /sys/bus/pci/drivers/e1000/0000:02:01.0
其实要做的事也就2步,然后我们可以把这些命令通过管道(|)来把命令连接起来,实现功能。
原创文章,作者:封于修,如若转载,请注明出处:http://www.178linux.com/4746
评论列表(7条)
才知道封于修不仅武功厉害,文章也相当牛了
@stanley:谢谢stanley大哥,不过我还有好长的路需要努力…呵呵
2、在/etc/passwd上查找用户id和组id在500到1099之间的行
grep “\” /etc/passwd
这样取是有问题的,[05]是取0或5,那ID为600-1000间的用户是取不到的。
中括号只能取一位数,我也不知道怎么取。
@老鼠上了猫:你说的对,我没有考虑清楚。其实严谨的写grep -E “[5-9][0-9][0-9]|10[0-9][0-9]” /etc/passwd 应该才是对的。
@封于修:你这是用户IP或组ID为500-1099:
grep -e “[5-9][0-9][0-9]” -e “10[0-9][0-9]” /etc/passwd 这样也可以
如果需满足用户IP和组IP为500-1099的话,只用grep想不出怎么匹配,用awk就比较简单了:
awk -F: ‘$3>=500 && $4<=1099 {print $0}' /etc/passwd
@老鼠上了猫:条件式的判断选取用awk是会更好。
grep其实也是可以的,就是会很麻烦。
grep -E “[^:]+:[^:]+:([5-9][0-9][0-9]|10[0-9][0-9]):([5-9][0-9][0-9]|10[0-9][0-9]):.*” /etc/passwd
我试了一下,这样写也是可以匹配得到的。或许会有更简便的写法,只能等大神解答了。
@封于修:整行匹配肯定没问题的,这也是一思路,赞!