Table of Contents
简介
使用Linux系统的过程中, 必然会遇到需要使用grep的情况。grep是Linux系统内置的工具。
(BSD和Unix中内置了grep, Windows 系统中可以安装 wingrep 或者 Cygwin)
GNU grep存在4种查询模式:
- 基本正则表达式查询
- 扩展正则表达式查询
- 定长字符串查询
- Perl风格正则表达式查询
概念总览
grep可以从文件或者输出流中查询字符串。经常使用来捕获日志文件中特定的文本;查询文件中符合特定模式的内容(比如查询身份证号码);查询某个内容是否在文件中存在。
有两种方式给grep工具提供输入: 指定文件, 将文件内容作为输入;使用管道符"|"将其他命令的输出结果作为grep的输入。
grep适合"查询", 对于"查找并替换"的需求, 使用"sed"以及"awk"更加有效。
基本正则
使用如下格式进行正则模式的搜索:
grep [options] [regexp] [filename]
正则表达式包括两类字符:文本字符与元字符。想要查询等于元字符的字面意思的文本时,需要在元字符前面加上反斜杠"\"。比如"*"表示出现任意次数, "\*"表示"星号"
如果希望搜索的文本中含有"空格"(Unix系统以空格作为分隔命令选项的分隔符), 需要将正则表达式使用引号将其包括其中。
- 使用单引号,可以在引号范围内使用空格
- 使用双引号,还可以在引号范围内使用环境变量, 比如"$HOME"
- 使用重音符"
", 可以使用shell命令执行结果, 比如
whoami`
正则匹配单个字符
元字符 | 名称 | 匹配功能 |
---|---|---|
. | 点 | 任意单个字符 |
[...] | 字符类 | 匹配中任意括号中列举的字符 |
[^...] | 负向字符类 | 匹配中任意括号中没有列举的字符 |
\char | 转移字符 | 匹配反斜杠之后的字符 |
正则匹配位置
元字符 | 名称 | 匹配功能 |
---|---|---|
^ | 托字符 | 行首 |
$ | 美元符 | 行末 |
< | 反斜杠+小于号 | 单词开头 |
> | 反斜杠+大于号 | 单词结尾 |
正则匹配数量(量词)
元字符 | 名称 | 匹配功能 |
---|---|---|
? | 问号 | 可选, 前一次表达式出现一次或不出现 |
* | 星号 | 前一个表达式出现任意次数,包括零次 |
+ | 加号 | 前一个表达式出现1次或多次 |
{N} | 精确次数匹配 | 匹配刚好N次 |
{N,} | 最小次数匹配 | 至少匹配N次 |
{min, max} | 指定次数区间匹配 | 匹配次数区间为[min, max] |
其他正则元字符
元字符 | 名称 | 匹配功能 |
---|---|---|
| | 替代选项 | 依次匹配给定表达式的某一个 |
- | 英文破折号 | 表示范围 |
(...) | 小括号 | 限制替代选项的范围 |
\1, \2, ... | 反引用 | 匹配之前小括号匹配到的文本 |
\b | 单词边界 | 匹配标记单词结束的一批符号 |
\B | 反斜杠 | "\\"的替代写法 |
\w | 单词字符 | 英文字符, 数字, 下划线 |
\W | 非单词字符 | 非"英文字符, 数字, 下划线" |
\` | buffer开头 | 匹配传给grep的buffer头 |
\' | buffer结尾 | 匹配传给grep的buffer尾 |
POSIX 字符定义
POSIX定义 | 字符定义的内容 |
---|---|
[:alpha:] | 任意英文字母表字符, 无论大小写 |
[:digit:] | 任意数字字符 |
[:alnum:] | 任意英文或数字字符 |
[:blank:] | 空白符或Tab符 |
[:xdigit:] | 十六进制字符, 包括所有数字字符和a-fA-F |
[:punct:] | 任意标点符号 |
[:print:] | 任意可打印字符(即控制字符之外的字符) |
[:space:] | 任意空白符 |
[:graph:] | 任意不是空白符的字符 |
[:upper:] | 任意大写字母 |
[:lower:] | 任意小写字母 |
[:cntrl:] | 控制字符 |
用法示例:
grep [[:alpha:]] test.txt
grep基础
grep会查询一行直到看到新的一行。在新的一行会重新使用表达式匹配。
配合基本正则
使用命令: grep
或者 grep -G
匹配控制
1-e pattern, --regexp=pattern 2 确保grep命令将模式文本识别为正则表达式 3-f file, --file=file 4 指定文件 5-i, --ignore 6 忽略大小写差异 7-v, --invert-match 8 反向匹配, 返回文本中不包含指定模式的行 9-w, --word-regexp 10 返回文本中完整匹配整个Word的行 11-x, --line-regexp 12 返回文本中整个行内容刚好等于正则表达式的行
基本输出控制
1-c, --count 2 不是输出具体文本内容, 而是输出匹配到的行数目(不是匹配项的数目) 3--color[=WHEN], --colour[=WHEN] 4 控制是否高亮, 值选项: auto, always, never 5-l, --files-with-matches 6 不是输出具体文本内容, 而是输出匹配到指定模式的文件的文件名 7-L, --files-without_match 8 不是输出具体文本内容, 而是输出没有匹配到指定模式的文件的文件名 9-m NUM, --max-count=NUM 10 指定在匹配到NUM行符合模式的行后, 停止搜索 11-o, --only-matching 12 只输出匹配到的内容, 即只输出高亮红色字体的部分 13-q, --quiet, --silent 14 用于给shell脚本确认是否查询到指定文本. match到时返回0, 没有match到时返回1, 报错退出时返回2
输出内容前缀控制
1-H, --with-filename 2 输出内容前带文件名 3-h, --no-filename 4 前缀不带文件名 5-n, --line_number 6 输出行号 7-T, --initial-tab 8 使用制表符来格式化输出. 比如: 9 test.txt: 1 :pattern 10-z, --null 11 每个filename之后输出一个ASCII NUL(a zero byte). 用于shell脚本, 识别文件名结尾
配合扩展正则
1使用命令: grep -E regexp filename 2比如: grep -E 'pat{2}ern|red' test.txt 3等于命令: grep -E 'pat\{2\}ern\|red' test.txt
样例:
基本正则模式 | 扩展正则模式 |
---|---|
'\(red\)' | '(red)' |
'a\{1,3\}' | 'a{1,3}' |
'behaviou?r' | 'behaviou?r' |
'pattern\+' | 'pattern+' |
定长字符串
使用命令: grep -F
性能
1grep -E '(0|2|4)' filename 2grep -E '[024]' filename
第二个命令的性能会更好些。因为"|"的使用, 会导致一个行会执行多次搜索
另一个可能造成问题的时对分组的引用, "\1\2" (性能消耗可能是几何级数增长)
Tips and Tricks
分组的使用
1测试文本 2The red dog fetches the green ball. 3The green dog fetches the blue ball. 4The blue dog fetches the blue ball. 5 6 7表达式 (red|green|blue).*(red|green|blue)可以匹配到每一行 8但是 (red|green|blue).*\1只能匹配到第三行, 因为只有第三行满足了"(red|green|blue)重复出现"这个条件
代码片
匹配目标 | 表达式 |
---|---|
IP addresses | \b[0-9]{1,3}(.[0-9]{1,3}){3} |
MAC addresses | \b[0-9a-f]{2}(:[0-9a-f]{2}){5}\b |
Email addresses | \b[a-z0-9]{1,}@*.(com |
美国Social Security numbers | '\b[0-9]{3}( |
搜索大文件
1使用命令: find / -print | xargs grep `ABCDEFGH` 2上述命令将搜索文件系统中的每个文件, 但是不会引发"打开太多文件"的错误