Linux 内置工具 grep 使用手册

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上述命令将搜索文件系统中的每个文件, 但是不会引发"打开太多文件"的错误
Mastodon