博客 / Linux/ shell脚本中grep命令详解

shell脚本中grep命令详解

shell脚本中grep命令详解

grep 简介

grep(global search regular expression(RE) and print out the line,全面搜索正则表达式并把行打印出来)是一种强大的文本搜索工具,它能使用正则表达式搜索文本,并把匹配的行打印出来。Unix/Linux 系统中的 grep 家族通常包括 grep、egrep 和 fgrep。

egrep 是 grep 的扩展版本,支持更多的正则表达式元字符。fgrep(fixed grep 或 fast grep)则将所有的字母都视为普通字符,即正则表达式中的元字符会失去特殊含义,仅代表其字面意义。在大多数 Linux 发行版中,使用的是 GNU 版本的 grep,它功能更强大,可以通过 -G(默认,基本正则)、-E(扩展正则,等同于 egrep)和 -F(固定字符串,等同于 fgrep)命令行选项来切换模式。

grep 的工作方式是在一个或多个文件中搜索给定的字符串模式(模板)。如果模式包含空格,则必须用引号引起来。模式之后的所有参数被视为文件名。搜索结果会输出到屏幕,而不会修改原文件。

grep 在 Shell 脚本中非常有用,因为它会返回一个状态值来指示搜索结果:

  • 0:表示搜索成功,找到了匹配项。
  • 1:表示搜索未成功,未找到匹配项。
  • 2:表示搜索的文件不存在或无法读取。

脚本可以利用这些返回值来进行条件判断和自动化文本处理。

grep 正则表达式元字符集(基本集)

以下是 grep 在默认模式(-G)下支持的基本正则表达式元字符:

  • ^:锚定行的开始。例如:'^grep' 匹配所有以 grep 开头的行。
  • $:锚定行的结束。例如:'grep$' 匹配所有以 grep 结尾的行。
  • .:匹配任意一个非换行符的字符。例如:'gr.p' 匹配 gr 后接任意一个字符,然后是 p。
  • *:匹配前一个字符零次或多次。例如:' *grep' 匹配零个或多个空格后紧跟 grep 的行。.* 组合表示匹配任意长度的任意字符(除换行符外)。
  • []:匹配一个指定范围内的字符。例如:'[Gg]rep' 匹配 Grep 和 grep。
  • [^]:匹配一个不在指定范围内的字符。例如:'[^A-FH-Z]rep' 匹配不以 A-F 和 H-Z 中字母开头,但紧跟 rep 的行。
  • (..):标记匹配的字符(分组),后续可用 1, 2 等引用。例如:'(love)',love 被标记为 1。
  • <:锚定单词的开始。例如:'<grep' 匹配包含以 grep 开头的单词的行。
  • >:锚定单词的结束。例如:'grep>' 匹配包含以 grep 结尾的单词的行。
  • x{m}:重复字符 x 恰好 m 次。例如:'o{5}' 匹配包含连续 5 个 o 的行。
  • x{m,}:重复字符 x 至少 m 次。例如:'o{5,}' 匹配至少有连续 5 个 o 的行。
  • x{m,n}:重复字符 x,至少 m 次,不多于 n 次。例如:'o{5,10}' 匹配 5 到 10 个连续的 o。
  • w:匹配文字和数字字符,等同于 [A-Za-z0-9_]。例如:'Gw*p' 匹配以 G 开头,后跟零个或多个文字数字字符,然后是 p。
  • Ww 的反置形式,匹配一个非单词字符(如标点、空格)。
  • b:单词边界。例如:'bgrepb' 只匹配独立的单词 grep。

用于 egrep 和 grep -E 的元字符扩展集

使用 egrepgrep -E 时,支持以下扩展元字符,语法更简洁:

  • +:匹配前一个字符一次或多次。例如:'[a-z]+able' 匹配一个或多个小写字母后跟 able 的字符串。
  • ?:匹配前一个字符零次或一次。例如:'gr?p' 匹配 grp 或 grep。
  • |:或操作,匹配多个模式之一。例如:'grep|sed' 匹配 grep 或 sed。
  • ():分组,无需转义。例如:'love(able|rs)ov+' 匹配 loveable 或 lovers,后跟一个或多个 ov。
  • x{m}, x{m,}, x{m,n}:功能同基本集中的 x{m} 等,但写法更简洁。

POSIX 字符类

为了保持不同语言环境字符编码的一致性,POSIX 标准定义了一些字符类。在 grep 中(除 fgrep 模式外),可以将它们放在 [[: :]] 内使用。例如,[[:alnum:]] 等同于 [A-Za-z0-9]

  • [:alnum:]:字母数字字符。
  • [:alpha:]:字母字符。
  • [:digit:]:数字字符。
  • [:graph:]:非空字符(非空格、控制字符)。
  • [:lower:]:小写字母。
  • [:cntrl:]:控制字符。
  • [:print:]:可打印字符(包括空格)。
  • [:punct:]:标点符号。
  • [:space:]:所有空白字符(空格、制表符、换行等)。
  • [:upper:]:大写字母。
  • [:xdigit:]:十六进制数字(0-9, a-f, A-F)。

Grep 常用命令选项

  • -A NUM, -B NUM, -C NUM:显示匹配行及其后(After)、前(Before)、前后(Context)各 NUM 行。原“-?”表述不准确,已修正。
  • -b, --byte-offset:在匹配行前打印该行在文件中的字节偏移量。
  • -c, --count:只打印匹配的行数,不显示具体内容。
  • -f FILE, --file=FILE:从指定文件中读取要搜索的模式。
  • -h, --no-filename:搜索多文件时,不显示文件名前缀。
  • -i, --ignore-case:忽略大小写。
  • -q, --quiet, --silent:静默模式,不输出任何信息,只通过退出状态返回结果。
  • -l, --files-with-matches:只打印包含匹配项的文件名。
  • -L, --files-without-match:只打印不包含匹配项的文件名。
  • -n, --line-number:显示匹配行的行号。
  • -s, --no-messages:不显示文件不存在或不可读的错误信息。
  • -v, --invert-match:反向匹配,只显示不匹配的行。
  • -w, --word-regexp:强制模式匹配整个单词。
  • -E, --extended-regexp:使用扩展正则表达式(等同于 egrep)。
  • -F, --fixed-strings:将模式视为固定字符串,而非正则表达式(等同于 fgrep)。
  • -V, --version:显示 grep 版本信息。

实例

掌握 grep 的关键在于熟练运用正则表达式。以下是一些常见的使用实例:

$ ls -l | grep '^a'

通过管道过滤 ls -l 的输出,只显示以字母 a 开头的行。

$ grep 'test' d*

显示所有以 d 开头的文件中包含字符串 test 的行。

$ grep 'test' aa bb cc

显示在 aa, bb, cc 三个文件中匹配 test 的行。

$ grep '[a-z]{5}' aa

显示文件 aa 中所有包含至少 5 个连续小写字母的字符串的行。

$ grep 'w(es)t.*1' aa

如果 west 被匹配,则其中的 es 会被存储并标记为第一组(1),然后搜索任意字符(.*)后面紧跟着另一个 es 的行。如果使用 egrepgrep -E,则无需对括号进行转义,可以直接写成 'w(es)t.*1'

发表评论

您的邮箱不会公开。必填项已用 * 标注。