Linux 内置工具 grep 使用手册

本文档介绍日常中使用grep的方法 "grep"是"Global RegularExpression Print"的首字母缩写, 使用过程中会涉及到正则表达式的使用 正则表达式的详细使用请查看正则表达式的文档

·
#1024程序员节#linux

Table of Contents

本文档介绍日常中使用grep的方法
"grep"是"Global RegularExpression Print"的首字母缩写, 使用过程中会涉及到正则表达式的使用
正则表达式的详细使用请查看正则表达式的文档

简介

使用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

匹配控制

-e pattern, --regexp=pattern
    确保grep命令将模式文本识别为正则表达式
-f file, --file=file
    指定文件
-i, --ignore
    忽略大小写差异
-v, --invert-match
    反向匹配, 返回文本中不包含指定模式的行
-w, --word-regexp
    返回文本中完整匹配整个Word的行
-x, --line-regexp
    返回文本中整个行内容刚好等于正则表达式的行

基本输出控制

-c, --count 
    不是输出具体文本内容, 而是输出匹配到的行数目(不是匹配项的数目)
--color[=WHEN], --colour[=WHEN] 
    控制是否高亮, 值选项: auto, always, never
-l, --files-with-matches 
    不是输出具体文本内容, 而是输出匹配到指定模式的文件的文件名
-L, --files-without_match
    不是输出具体文本内容, 而是输出没有匹配到指定模式的文件的文件名
-m NUM, --max-count=NUM
    指定在匹配到NUM行符合模式的行后, 停止搜索
-o, --only-matching
    只输出匹配到的内容, 即只输出高亮红色字体的部分
-q, --quiet, --silent
    用于给shell脚本确认是否查询到指定文本. match到时返回0, 没有match到时返回1, 报错退出时返回2

输出内容前缀控制

-H, --with-filename
    输出内容前带文件名
-h, --no-filename
    前缀不带文件名
-n, --line_number
    输出行号
-T, --initial-tab
    使用制表符来格式化输出. 比如:
    test.txt:   1  :pattern
-z, --null
    每个filename之后输出一个ASCII NUL(a zero byte). 用于shell脚本, 识别文件名结尾

配合扩展正则

使用命令: grep -E regexp filename
比如: grep -E 'pat{2}ern|red' test.txt
等于命令: grep -E 'pat\{2\}ern\|red' test.txt

样例:

基本正则模式扩展正则模式
'\(red\)''(red)'
'a\{1,3\}''a{1,3}'
'behaviou?r''behaviou?r'
'pattern\+''pattern+'

定长字符串

使用命令: grep -F

性能

grep -E '(0|2|4)' filename
grep -E '[024]' filename

第二个命令的性能会更好些。因为"|"的使用, 会导致一个行会执行多次搜索

另一个可能造成问题的时对分组的引用, "\1\2" (性能消耗可能是几何级数增长)

Tips and Tricks

分组的使用

测试文本
The red dog fetches the green ball.
The green dog fetches the blue ball.
The blue dog fetches the blue ball.
 
 
表达式 (red|green|blue).*(red|green|blue)可以匹配到每一行
但是 (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}(

搜索大文件

使用命令: find / -print | xargs grep `ABCDEFGH`
上述命令将搜索文件系统中的每个文件, 但是不会引发"打开太多文件"的错误