44468

222 分钟

#Bash 的 grep 命令

grep [OPTION]... PATTERNS [FILE]...

功能

搜索文件中匹配的行。

类型

可执行文件(/usr/bin/grep)。

参数

  • OPTION 选项:
    • -E, --extended-regexp - 使用扩展正则(EREs)
    • -F, --fixed-strings - 不使用正则,PATTERNS 试做普通字符串
    • -G, --basic-regexp - 使用基本正则(BRGs);默认
    • -P, --perl-regexp - 使用 Perl 正则(PCREs)
    • -e PATTERNS, --regexp=PATTERNS - 指定正则表达式,可以多次使用此选项指定多个表达式
    • -f FILE, --file=FILE - 从 FILE 文件中获取正则表达式,每行表示一个正则表达式
    • -i, --ignore-case - 忽略大小写
    • --no-ignore-case - 不要忽略大小写
    • -v, --invert-match - 反转匹配(选择不匹配的行)
    • -w, --word-regexp - 仅选择匹配完整单词的行
    • -x, --line-regexp - 仅选择匹配整行的行
    • -c, --count - 只显示各个文件匹配的行数
    • --color[=WHEN], --colour[=WHEN] - 何时显示彩色;取值为:never, always, 或 auto
    • -L, --files-without-match - 只显示无匹配行的文件名
    • -l, --files-with-matches - 只显示有匹配行的文件名
    • -m NUM, --max-count=NUM - 最多匹配 NUM
    • -o, --only-matching - 只显示匹配的部分,而非匹配的行
    • -q, --quiet, --silent - 不打印任何内容,仅通过返回值返回是(0)否(非 0)存在匹配
    • -s, --no-messages - 忽略文件不存在或不可读的错误
    • -b, --byte-offset - 在每行输出前打印从 0 开始字节偏移量
    • -H, --with-filename - 打印文件名;默认
    • -h, --no-filename - 不打印文件名
    • --label=LABEL - 将来自标准输入的数据当作来自 LABEL 文件
    • -n, --line-number - 打印从 1 开始的行号
    • -T, --initial-tab - 确保打印行的第一个字符在制表位上
    • -Z, --null - 文件名后跟空字符(\0)代替原本的字符(通常是 :\n
    • -A NUM, --after-context=NUM - 打印匹配行之后的 NUM
    • -B NUM, --before-context=NUM - 打印匹配行之前的 NUM
    • -C NUM, -NUM, --context=NUM - 打印匹配行之前和之后各 NUM
    • --group-separator=SEP - 使用 -A,-B,-C 打印多行时,使用 SEP 分隔不同的匹配;默认为 --
    • --no-group-separator - 使用 -A,-B,-C 打印多行时,不进行分隔
    • -a, --text - 将二进制文件试做文本文件;等价于 --binary-files=text
    • --binary-files=TYPE - 将二进制文件视作 TYPE 类型的文件
      • binary - 忽略并警告;默认
      • text - 视作文本文件进行匹配
      • without-match - 忽略
    • -D ACTION, --devices=ACTION - 遇到设备文件时进行的操作
      • read - 当作普通文件读取并匹配
      • skip - 跳过
    • -d ACTION, --directories=ACTION - 遇到目录文件时进行的操作
      • read - 当作普通文件读取并匹配
      • skip - 跳过
      • recurse - 递归读取目录中的所有文件
    • --exclude=GLOB - 文件名以通配符模式匹配 GLOB 时,跳过该文件
    • --exclude-from=FILE - 文件名以通配符模式匹配 FILE 中的任意行时,跳过该文件
    • --exclude-dir=GLOB - 文件名以通配符模式匹配 GLOB 时,跳过该目录
    • -I - 忽略二进制文件;等价于 --binary-files=without-match
    • --include=GLOB - 文件名以通配符模式匹配 GLOB 时,包含该文件;跳过其它文件
    • -r, --recursive - 递归搜索目录;等价于 --directories=recurse
    • -R, --dereference-recursive - 递归搜索目录,并跟踪符号链接
    • --line-buffered - 输出时使用行缓冲
    • -U, --binary - 将文件视作二进制文件
    • -z, --null-data - 以空字符(\0)作为行的结尾,而不是换行符(\n
    • --help - 显示当前帮助
    • --version - 显示版本
  • PATTERNS - 正则表达式
  • FILE - 文件列表;可以是目录
    • 如果此参数设为 - 则读取标准输入
    • 如果省略此参数,则递归搜索当前工作目录

#正则表达式

grep 主要支持三种风格的正则:基本正则 (BRE - Basic Regular Expression)扩展正则 (ERE - Extended Regular Expression)Perl 正则 (PCRE - Perl Compatible Regular Expressions)

核心差异对比

特性基本正则 (BRE)扩展正则 (ERE)Perl 正则 (PCRE)
选项无 (默认)-E-P
次数匹配 {n,m}\{n,m\}{n,m}{n,m}
分组 ()\(\)()()
或运算 |\|||
1次或多次 +\+++
0次或1次 ?\???
预定义类 (如 \d)不支持不支持支持
非贪婪匹配不支持不支持支持

#基本正则表达式

这是 grep 默认使用的模式。它的原则是“尽量把字符当成普通文本”,因此很多特殊元字符需要通过反斜杠 \ 转义后才具有特殊含义。

  • ?, +, {, |, (, ) 这些符号在 BRE 中被视为普通字符。
  • 如果要使用它们的正则功能,必须转义:\?, \+, \{, \|, \(

#扩展正则表达式

ERE 简化了语法,去掉了大部分反斜杠。它认为这些特殊符号“天生”就应该是功能符号。

  • 使用 -E 选项开启
  • ?, +, {, |, (, ) 直接作为正则的元字符使用,无需转义。
  • 如果要将它们当作普通字符,必须转义:\?, \+, \{, \|, \(

#Perl 正则表达式

这是最强大的正则风格。它不仅包含 ERE 的所有功能,还加入了许多高级特性(如环视、非贪婪匹配等)。

  • 使用 -P 选项开启
  • 支持特殊的预定义字符集,如 \d (数字), \w (字母数字下划线), \s (空白符)。
  • 支持非贪婪模式(在量词后加 ?)。
字符描述
\将下一个字符标记为一个特殊字符(File Format Escape,清单见本表)、或一个原义字符(Identity Escape,有“^$()*+?.[{|\”共计12个)、或一个向后引用(backreferences)、或一个八进制转义符。例如,“n”匹配字符“n”。“\n”匹配一个换行符。序列“\”匹配“\”而“(”则匹配“(”。
^匹配输入字符串的开始位置。如果设置了RegExp对象的Multiline属性,^也匹配“\n”或“\r”之后的位置。
$匹配输入字符串的结束位置。如果设置了RegExp对象的Multiline属性,$也匹配“\n”或“\r”之前的位置。
*匹配前面的子表达式零次或多次。例如,zo*能匹配“z”、“zo”以及“zoo”。*等价于{0,}。
+匹配前面的子表达式一次或多次。例如,“zo+”能匹配“zo”以及“zoo”,但不能匹配“z”。+等价于{1,}。
?匹配前面的子表达式零次或一次。例如,“do(es)?”可以匹配“does”中的“do”和“does”。?等价于{0,1}。
{n}n是一个非负整数。匹配确定的n次。例如,“o{2}”不能匹配“Bob”中的“o”,但是能匹配“food”中的两个o。
{n,}n是一个非负整数。至少匹配n次。例如,“o{2,}”不能匹配“Bob”中的“o”,但能匹配“foooood”中的所有o。“o{1,}”等价于“o+”。“o{0,}”则等价于“o*”。
{n,m}m和n均为非负整数,其中n<=m。最少匹配n次且最多匹配m次。例如,“o{1,3}”将匹配“fooooood”中的前三个o。“o{0,1}”等价于“o?”。请注意在逗号和两个数之间不能有空格。
?非贪心量化(Non-greedy quantifiers):当该字符紧跟在任何一个其他重复修饰符(*,+,?,{n},{n,},{n,m})后面时,匹配模式是非贪婪的。非贪婪模式尽可能少的匹配所搜索的字符串,而默认的贪婪模式则尽可能多的匹配所搜索的字符串。例如,对于字符串“oooo”,“o+?”将匹配单个“o”,而“o+”将匹配所有“o”。
.匹配除“\r”“\n”之外的任何单个字符。要匹配包括“\r”“\n”在内的任何字符,请使用像“(.|\r|\n)”的模式。
(pattern)匹配pattern并获取这一匹配的子字符串。该子字符串用于向后引用。所获取的匹配可以从产生的Matches集合得到,在VBScript中使用SubMatches集合,在JScript中则使用9属性。要匹配圆括号字符,请使用“(”或“)”。可带数量后缀。
(?:pattern)匹配pattern但不获取匹配的子字符串(shy groups),也就是说这是一个非获取匹配,不存储匹配的子字符串用于向后引用。这在使用或字符“(|)”来组合一个模式的各个部分是很有用。例如“industr(?:y
(?=pattern)正向肯定预查(look ahead positive assert),在任何匹配pattern的字符串开始处匹配查找字符串。这是一个非获取匹配,也就是说,该匹配不需要获取供以后使用。例如,“Windows(?=95|98|NT|2000)”能匹配“Windows2000”中的“Windows”,但不能匹配“Windows3.1”中的“Windows”。预查不消耗字符,也就是说,在一个匹配发生后,在最后一次匹配之后立即开始下一次匹配的搜索,而不是从包含预查的字符之后开始。
(?!pattern)正向否定预查(negative assert),在任何不匹配pattern的字符串开始处匹配查找字符串。这是一个非获取匹配,也就是说,该匹配不需要获取供以后使用。例如“Windows(?!95|98|NT|2000)”能匹配“Windows3.1”中的“Windows”,但不能匹配“Windows2000”中的“Windows”。预查不消耗字符,也就是说,在一个匹配发生后,在最后一次匹配之后立即开始下一次匹配的搜索,而不是从包含预查的字符之后开始
(?<=pattern)反向(look behind)肯定预查,与正向肯定预查类似,只是方向相反。例如,“(?<=95|98|NT|2000)Windows”能匹配“2000Windows”中的“Windows”,但不能匹配“3.1Windows”中的“Windows”。
(?<!pattern)反向否定预查,与正向否定预查类似,只是方向相反。例如“(?<!95|98|NT|2000)Windows”能匹配“3.1Windows”中的“Windows”,但不能匹配“2000Windows”中的“Windows”。
x|y没有包围在()里,其范围是整个正则表达式。例如,“z|food”能匹配“z”或“food”。“(?:z|f)ood”则匹配“zood”或“food”。
[xyz]字符集合(character class)。匹配所包含的任意一个字符。例如,“[abc]”可以匹配“plain”中的“a”。特殊字符仅有反斜线\保持特殊含义,用于转义字符。其它特殊字符如星号、加号、各种括号等均作为普通字符。脱字符^如果出现在首位则表示负值字符集合;如果出现在字符串中间就仅作为普通字符。连字符 - 如果出现在字符串中间表示字符范围描述;如果如果出现在首位(或末尾)则仅作为普通字符。右方括号应转义出现,也可以作为首位字符出现。
[^xyz]排除型字符集合(negated character classes)。匹配未列出的任意字符。例如,“[^abc]”可以匹配“plain”中的“plin”。
[a-z]字符范围。匹配在Unicode编码表指定范围内的任意字符。例如,“[a-z]”可以匹配“a”到“z”范围内的任意小写字母字符。
[^a-z]排除型的字符范围。匹配任何不在Unicode编码表指定范围内的任意字符。例如,“[^a-z]”可以匹配任何不在“a”到“z”范围内的任意字符。
[:name:]增加命名字符类(named character class)[注 1]中的字符到表达式。只能用于方括号表达式。
[=elt=]增加当前locale下排序(collate)等价于字符“elt”的元素。例如,[=a=]可能会增加ä、á、à、ă、ắ、ằ、ẵ、ẳ、â、ấ、ầ、ẫ、ẩ、ǎ、å、ǻ、ä、ǟ、ã、ȧ、ǡ、ą、ā、ả、ȁ、ȃ、ạ、ặ、ậ、ḁ、ⱥ、ᶏ、ɐ、ɑ 。只能用于方括号表达式。
[.elt.]增加排序元素(collation element)elt到表达式中。这是因为某些排序元素由多个字符组成。例如,29个字母表的西班牙语, "CH"作为单个字母排在字母C之后,因此会产生如此排序“cinco, credo, chispa”。只能用于方括号表达式。
\b匹配一个单词边界,也就是指单词和空格间的位置。例如,“er\b”可以匹配“never”中的“er”,但不能匹配“verb”中的“er”。
\B匹配非单词边界。“er\B”能匹配“verb”中的“er”,但不能匹配“never”中的“er”。
\cx匹配由x指明的控制字符。x的值必须为A-Z或a-z之一。否则,将c视为一个原义的“c”字符。控制字符的值等于x的值最低5比特(即对3210进制的余数)。例如,\cM匹配一个Control-M或回车符。\ca等效于\u0001, \cb等效于\u0002, 等等...
\d匹配一个数字字符。等价于[0-9]。注意Unicode正则表达式会匹配全角数字字符。
\D匹配一个非数字字符。等价于[^0-9]。
\f匹配一个换页符。等价于\x0c和\cL。
\n匹配一个换行符。等价于\x0a和\cJ。
\r匹配一个回车符。等价于\x0d和\cM。
\s匹配任何空白字符,包括空格、制表符、换页符等等。等价于[ \f\n\r\t\v]。注意Unicode正则表达式会匹配全角空格符。
\S匹配任何非空白字符。等价于[^ \f\n\r\t\v]。
\t匹配一个制表符。等价于\x09和\cI。
\v匹配一个垂直制表符。等价于\x0b和\cK。
\w匹配包括下划线的任何单词字符。等价于“[A-Za-z0-9_]”。注意Unicode正则表达式会匹配中文字符。
\W匹配任何非单词字符。等价于“[^A-Za-z0-9_]”。
\xnn十六进制转义字符序列。匹配两个十六进制数字nn表示的字符。例如,“\x41”匹配“A”。“\x041”则等价于“\x04&1”。正则表达式中可以使用ASCII编码。.
\num向后引用(back-reference)一个子字符串(substring),该子字符串与正则表达式的第num个用括号围起来的捕捉群(capture group)子表达式(subexpression)匹配。其中num是从1开始的十进制正整数,其上限可能是9[注 2]、31[注 3]、99甚至无限[注 4]。例如:“(.)\1”匹配两个连续的相同字符。
\n标识一个八进制转义值或一个向后引用。如果\n之前至少n个获取的子表达式,则n为向后引用。否则,如果n为八进制数字(0-7),则n为一个八进制转义值。
\nm3位八进制数字,标识一个八进制转义值或一个向后引用。如果\nm之前至少有nm个获得子表达式,则nm为向后引用。如果\nm之前至少有n个获取,则n为一个后跟文字m的向后引用。如果前面的条件都不满足,若n和m均为八进制数字(0-7),则\nm将匹配八进制转义值nm。
\nml如果n为八进制数字(0-3),且m和l均为八进制数字(0-7),则匹配八进制转义值nml。
\unUnicode转义字符序列。其中n是一个用四个十六进制数字表示的Unicode字符。例如,\u00A9匹配著作权符号(©)。

#示例

基本示例

$ grep "error" log.txt                      # 在 log.txt 中搜索含有 "error" 的行
$ grep -i "error" log.txt                   # 忽略大小写
$ grep -n "error" log.txt                   # 显示行号
$ grep -c "error" log.txt                   # 统计匹配的行数
$ grep -v "error" log.txt                   # 在 log.txt 中搜索不含 "error" 的行

递归搜索目录

$ grep "TODO" -r ./src                      # 在 ./src 目录中搜索包含 "TODO" 的行,不跟踪符号链接
$ grep "error" -R /var/log                  # 在 /var/log 目录中搜索包含 "error" 的行,并且跟踪符号链接

显示上下文

$ grep "TODO" -A 10 ./src                   # 现在匹配的行以及之后的 10 行
$ grep "TODO" -B 10 ./src                   # 现在匹配的行以及之前的 10 行
$ grep "TODO" -C 10 ./src                   # 现在匹配的行以及前后各 10 行

正则表达式

$ grep "^#" file.txt                        # 搜索以 # 开头的行
$ grep -E "error|fail|panic" log.txt        # 使用扩展正则,“或”关系不需要转义
$ grep -E "[0-9]+" file.txt                 # 匹配十进制数字串
$ grep -P "[\w.-]+@[\w.-]+\.\w+" file.txt   # 匹配邮箱地址,使用 Perl 正则,支持 \w 等预定义字符集

信息提取

$ grep -o "[0-9]\+" file.txt                # 只输出匹配的部分
$ grep -oP "(?<=:)\d+" url.txt              # 提取端口号
$ grep -oP "(?<=user=)\w+" log.txt          # 提取 user= 的值

#推荐阅读

#手册

更新: 2026/2/6

作者: PlanC

创建: 2026/2/5