本文转载自:如何使用Unix/Linux grep命令——磨刀不误砍柴工系列。该博文条理很清晰。
grep简介
grep在一个或多个文件中查找与模式字符串(pattern)匹配的行,并将搜索的结果打印出来,不会修改原文件内容。使用grep 命令的语法为:
$grep [option(s)] pattern [file(s)]
其中option为grep命令的选项,pattern为要匹配的简单字符串或携带特殊字符的模式字符串,file为文件列表,可有多个文件。
grep中经常用到的选项
-i 忽略pattern中的大小写
$grep -i hAL /etc/passwd
-w 搜索整个词汇
忽略大小写并搜索整个词汇"samba"
$grep -iw "samba" /tec/samba/smb.conf # This is the main Samba configuration file. You should read the # here. Samba has a huge number of configurable options (perhaps too # For a step to step guide on installing, configuring and using samba, # read the Samba-HOWTO-Collection. This may be obtained from:
-r 递归地指定文件所在目录中的所有子目录中的文件
-v 查找与pattern不匹配的行
定义输出方式:
-o 仅打印出匹配的一段,而非整行
-n 打印出匹配行的行号
-l 仅打印出匹配行所在的文件
-c 打印出每个文件中匹配行的总数
-A num 显示匹配行之后的num行
-B num 显示匹配行之前的num行
-C num 相当于 -A num 与 -B num 的组合
--color=auto 将pattern在匹配行中高亮输出
注意:
1)选项区分大小写
2)多个选项可以一起使用,例如:
$grep -iwr
3)grep可用于shell脚本,因为grep通过返回一个状态值来说明搜索的状态,如果模板搜索成功,则返回0,如果搜索不成功,则返回1,如果搜索的文件不存在,则返回2。我们利用这些返回值就可进行一些自动化的文本处理工作。
在grep中使用正则表达式
基本的匹配模式
尽管直接使用最简单直接的pattern字串可以完成一些重要任务,但是grep命令的真正威力在于它可以使用正则表达式来完成复杂的模式字串的匹配。grep命令中使用的是“基本的正则表达式”,如果想使用更高级的正则表达式规则,需要指定选项 -E ,相当于egrep命令。
以下字符或字符串在正则表达式的规则中具有特殊意义,如,*,+,[,],^,$,\,{,}
它们的多种组合展示了基本的正则表达式的匹配模式:
1)'.'匹配任意单一字符
2)X* 与包含连续0个或多个字符X的行匹配
3)X\+ 与包含连续1个或多个字符X的行匹配
4)[a-z] 与包含a-z的其中一个字符的行匹配
5)[^a-z] 与不包含a-z的其中一个字符的行匹配
6)[0-9] 与包含0-9的其中一个字符的行匹配
7)^hello 与以字串hello起始的行匹配
8)hello$ 与以字串hello结束的行匹配
9)\ 转义字符,后跟特殊字符,可表示它本来的涵义
10)
\d 匹配一个数字字符,等价于 [0-9]
\D 匹配一个非数字符,等价于 [^0-9]
\w 等价于 "[A-Za-z0-9_]"
\W 匹配任何非单词字符,等价于 "[^A-Za-z0-9]"
\s 匹配任何空白字符,包括空格、制表符、换页符等等,等价于[\f\n\r\t\v]
\S 匹配任何非空白字符,等价于 [^\f\r\n\t\v]
\b 匹配一个单词边界,也就是指单词和空格间的位置。
\B 匹配非单词边界。
如,
$grep '[' filename
返回结果为grep : Invalid regular expression
而,
$grep '\[' filename
会匹配所有包含‘['(不包括单引号)的行。
11)
X\{n\} 与连续包含n个字符X的行匹配
X\ {n,\} 与至少连续包含n个字符X的行匹配 (注意n后面的',')
X\{,m\} 与最多连续包含m个字符X的行匹配 (注意m前面的',')
X\{n,m\} 与最少包含n个,最多包含m个字符X的行匹配
注意:
不要混淆shell 中的"."、"*"与正则表达式中的"."、"*",很多刚开始学的人都会犯错。
在正则表达式中,"."很像shell中的"?",它与任意单一字符匹配。而"*"在正则表达式中的使用,表示"*"前面的字符可能出现0次或1次或多次,与shell中的"*"涵义不同。
grep中模式操作(与或非)
1)grep OR 操作(4 种方法)
A. 使用 \|
$grep 'pattern1\|pattern2' filename
B. 使用 -E 选项
grep -E 代表扩展的正则表达式. 若使用-E选项,则可以去掉转义字符'\',直接使用'|'
$grep -E 'pattern1|pattern2' filename
C. 使用 egrep 命令
egrep 相当于 ‘grep -E’.
D. 使用 -e 选项
通过指定多个-e选项来应用多个pattern,多个pattern之间是“或”的关系
$grep -e pattern1 -e pattern2 filename
2)grep AND 操作
A. 使用 -E选项和模式字符 'pattern1.*pattern2'
$grep -E 'pattern1.*pattern2' filename
以上命令为在filename文件中查找既与pattern1匹配又与pattern2匹配的行
$grep -E 'pattern1.*pattern2|pattern2.*pattern1' filename
B. 利用管道实现
$grep -E 'pattern1' filename | grep -E 'pattern2'
3)grep NOT 操作
A. 使用 -v 选项
$grep -v 'pattern' filename
以上命令在filename文件中查找不能与pattern匹配的行
示例
1)对文件中的空行计数
$grep -c "^$" filename
2)查找在“hello”有任意长度字串的行
$grep ".*hello" filename
3)查找在'hi'与'hello'之间至少有一个空格的行
$grep "hi \+hello" filename
4)查找在'hi'与'hello'之间没有空格或有多个空格的行
$grep "hi *hello" filename
5)查找在'hi'与'hello'之间没有空格或有1个空格的行
$grep "hi \?hello" filename
6)查找ip地址127.0.0.1 (其中包含特殊字符 '.')
$grep "127\.0\.0\.1" filename
7)过滤其他命令的输出结果
$ls --help | grep "dired"
将ls命令的帮助文本,作为grep的输入,查找与"dired"匹配的行
输出为:-D, --dired generate output designed for Emacs' dired mode
8)从系统日志中获得有用的信息
在apache日志文件中查找以IP地址开头,包含数字200的行
$grep -Eoc "^[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}.* 200" /srv/www/example.com/logs/access.log