grep是一个最初用于Unix操作系统的命令行工具。在给出文件列表或标准输入后,grep会对匹配一个或多个正则表达式的文本进行搜索,并只输出匹配(或者不匹配)的行或文本。
egrep是grep的扩充版本,改良了grep不能或不方便的操作,主要是正则匹配方面的扩展。
fgrep不做正则处理,表达式仅作为一般字符串处理,所有正则元字符不起作用。
调用grep
一般的grep命令行是:grep options pattern input_file_names
可以有零个或多个options和input_file_names,可以用-e pattern
或-f file
选项来指定多个正则表达式。
grep 常用选项
-v
:逆反模式,只输出不匹配的行。-r
:递归搜索目录。-q
:静默模式,不输出任何结果(stderr除外,用于获取命令返回值,有匹配为true,否则为false)。-i
:忽略大小写区别。-w
:整个单词匹配。-n
:同时输出行号。-c
:只输出匹配的行数。-l
:只输出含有匹配行的文件名。-E
:切换到egrep。
举例
grep -l 'main' *.c
:在当前目录下的所有c源文件里搜索含有main
的文件,只输出文件名。
grep -r 'hello' /home/gigi
:递归地搜索目录。
find /home/gigi -name "*.c" -print0 | xargs -0r grep -H 'hello'
:在/home/gigi
目录下的所有c文件里搜索hello
,类似于:grep -rH --include='*.c' 'hello' /home/gigi
。
grep -e '--cut here--' *
:如果模式以-
开头,需要使用-e
选项,否则grep是尝试当作选项列表来解析。
grep -w 'hello' *
:搜索一个完整的单词,而不是作为单词的一部分。
grep -C 2 'hello' *
:输出匹配行的上下文,前后各2行。
grep -H 'eli' /etc/passwd /dev/null
:强制grep输出匹配行所在的文件名。
ps -ef | grep '[c]ron
:这里之所以要使用字符集[]
模式,是为了避免匹配到这条命令本身。
grep 'paul' /etc/motd | grep 'franc,ois'
:grep没法表示一个逻辑与的概念,如果需要同时匹配多个模式,需要使用多个grep命令。
cat /etc/passwd | grep 'alain' - /etc/motd
:同时在标准输入和输入文件里查找。-
表示标准输入。
echo -e "123321\nabcxyz\nabcba" | grep -e '\(.\)\(.\).\2\1'
:用正则表达式表示回文。能够匹配的回文多达19个字符:
echo "1234567890987654321" | grep -E -e '^(.?)(.?)(.?)(.?)(.?)(.?)(.?)(.?)(.?).?\9\8\7\6\5\4\3\2\1$'
grep完整的选项
- 匹配控制
-e pattern, --regexp=pattern
:用pattern
作为正则表达式。这用于指定多个搜索正则表达式,或用于保护以-
开头的正则表达式(-e
由POSIX规定)。-f file, --file=File
: 从文件中提取,空文件中包含0个正则表达式,所以什么都不匹配(-f
由POSIX规定)。-i, --ignore-case, -y
:忽略正则表达式和输入文件的大小写差别。-y
是一个过时的同义词,用于兼容性(-i
由POSIX规定)。-v, --revert-match
:反检索,只选择不匹配的行(-v
由POSIX规定)。-w, --word-regexp
:(把模式当作整个单词,而不是单词的一部分来匹配)只选择那些内容里匹配整个单词的行。测试规则是匹配的子字符串必须是在行的开头或前面是非单词组成字符,
类似地,它必须在行的结尾或后接一个非单词组成字符。单词组成字符是字母、数字和下划线。( 如果被\<
和\>
引用,就把表达式作为一个单词搜索。)-x, --line-regexp
:只选择那些刚好匹配整行的行(-x
由POSIX规定)。
- 一般的输出控制
-c, --count
:只打印每个文件的匹配行数,不显示匹配的内容。和-v, --invert-match
选项一起时,计算不匹配的行数。(-c
由POSIX规定)。--color[=WHEN], --colour[=WHEN]
:-l, --files-with-matches
:打印匹配模板的文件清单。-L, --files-without-match
:打印不匹配模板的文件清单。-m num, --max-count=num
:在一个文件找到num个匹配后停止读取。-o, --only-matching
:只显示匹配行的匹配的部分,每个匹配部分单独一行输出。-q, --quiet, --silent
:安静,不输出任何信息到stdout。在找到任何匹配后立即以状态0退出,即使检测到错误。(-q
由POSIX规定)。-s, --no-messages
:不显示关于不存在或者无法读取文件的错误信息。
- 输出行前缀控制
-b, --byte-offset
:在匹配行前面打印该行所在输入文件内的字节偏移,偏移是基于0的。如果指定了-o, --only-matching
,打印匹配部分自己的偏移。
当grep允许在Ms-DOS或MS-Windows,打印的字节偏移取决于是否使用了-u, --unix-byte-offsets
选项。-h, --no-filename
:在输出上不前缀文件名。当只搜索一个文件时,这是默认的。-H, --with-filename
:在每个匹配前打印文件名。当搜索文件不止一个时,这是默认的。--label=LABEL
:Display input actually coming from standard input as input coming from file LABEL.
This is especially useful when implementing tools like zgrep; e.g.:gzip -cd foo.gz | grep --label=foo -H something
-n, --line-number
:在匹配的行前面打印所在输入文件内的行号,行号是基于1的。-T, --initial-tab
:Make sure that the first character of actual line content lies on a tab stop, so that the alignment of tabs looks normal.
This is useful with options that prefix their output to the actual content: -H, -n, and -b. In order to improve the probability that lines from a single file will all start at the same column,
this also causes the line number and byte offset (if present) to be printed in a minimum-size field width.-u, --unix-byte-offsets
:Report Unix-style byte offsets. This option causes grep to report byte offsets as if the file were a Unix-style text file, i.e., the byte offsets ignore the CR
characters that were stripped. This will produce results identical to running grep on a Unix machine. This option has no effect unless the -b option is also used;
it has no effect on platforms other than MS-DOS and MS-Windows.-z, --null
:Output a zero byte (the ASCII NUL character) instead of the character that normally follows a file name. For example, ‘grep -lZ’ outputs a zero byte after each file
name instead of the usual newline. This option makes the output unambiguous, even in the presence of file names containing unusual characters like newlines.
This option can be used with commands like ‘find -print0’, ‘perl -0’, ‘sort -z’, and ‘xargs -0’ to process arbitrary file names, even those that contain newline characters.
- 上下文行控制
-A num, --after-context=num
:打印匹配行后面的num行。-B num, --before-context=num
:打印匹配行前面的num行。-C num, --context=num, -num
:打印匹配行前面的num行和后面的num行。如grep -2 pattern file
,同时显示匹配行的上下2行。--group-seprator=string
:当使用了-A, -B, -C
选项时,print string instead of — around disjoint groups of lines.(没啥效果)--no-group-seprator
:当使用了-A, -B, -C
选项时, print disjoint groups of lines adjacent to each other.(没啥效果)
- 文件和目录选择
-a, --text
:处理二进制文件当作文本处理;这等价于--binary-files=text
选项。--binary-files=type
:如果一个文件的资源配置元数据或它的开头几个字节表明文件包含二进制数据,假设文件是type
类型的。默认地,type
是binary
,
grep一般输出一个单行信息说明匹配到一个二进制文件,或不输出信息如果没有匹配。
如果type
是without-match
,grep假设二进制文件不匹配,这等价于-I
选项。
如果type
是text
,grep把二进制文件当作文本处理,等价于-a
选项。
警告:--binary-files=text
可能输出二进制垃圾,这可能带来严重的负面作用,如果输出是终端,而终端驱动把一些输出解释为命令。-D action, --devices=action
:如果输入文件是设备、FIFO或socket,用action
来处理。如果action是read,所有设备被当作普通文件读取。如果action是skip,设备、FIFO和sockets被跳过。
By default, devices are read if they are on the command line or if the -R (–dereference-recursive) option is used, and are skipped if they are encountered recursively and the -r (–recursive)
option is used. This option has no effect on a file that is read via standard input.-d action, --directories=action
:If an input file is a directory, use action to process it. By default, action is ‘read’, which means that directories are read just as if they were ordinary
files (some operating systems and file systems disallow this, and will cause grep to print error messages for every directory or silently skip them). If action is ‘skip’, directories are silently
skipped. If action is ‘recurse’, grep reads all files under each directory, recursively, following command-line symbolic links and skipping other symlinks; this is equivalent to the -r option.--exclude=glob
:跳过base name(文件名,不包括路径)匹配glob(使用通配符匹配)的文件。文件名glob可以使用*
,?
,[...]
作为通配符,用\
转义通配符。--exclude-from=file
:跳过base name匹配任何从file里读取的文件名glob(使用在--exclude
描述的通配符匹配。)--exclude-dir=dir
:在递归搜索中排除匹配正则表达式pattern的目录。-I
:不匹配二进制文件。等价于--binary-files=without-match
选项。--include=glob
:只搜索base name匹配glob的文件。(使用在--exclude
描述的通配符匹配。)-r, --recursive
:递归处理目录。解析符号链接,但跳过递归引用的链接。等价于--directories=recurse
选项。-R, --dereference-recursive
:递归处理目录,解析所有符号链接。
- 一般的程序信息
--help
:输出命令行选项的简洁使用信息,和bug报告地址,然后退出。-V, --version
:显示软件版本信息。
- 其他选项
--line-buffered
:在输出上使用行缓存,这可能需要性能代价。--mmap
:这个选项已被废弃。-U, --binary
:把文件当作二进制文件。z, --null-data
:把输入当作行的集合,每个由字节0(ASCII的NULL字符)而不是换行结束。和-Z, --null
选项一样,这个选项可用于和命令如sort -z
一起使用,用于处理任意文件名。
grep如何选择前缀字段与内容行之间的分隔符
- 匹配行一般使用冒号
:
作为前缀字段与内容行之间的分隔符。 - 上下文行使用
-
。 - 当没有指定上下文,匹配行只是简单地跟在前一个的后面输出。
- When nonzero context is specified, lines that are adjacent in the input form a group and are output one right after another, while a separator appears by default
between disjoint groups on a line of its own and without any prefix. - The default separator is ‘–’, however whether to include it and its appearance can be changed with the options above.
- Each group may contain several matching lines when they are close enough to each other that two otherwise adjacent but divided groups connect and can just merge into a single contiguous one.
参考链接
正则表达式元字符集(基本集)
^ 锚定行的开始。
$ 锚定行的结束。
. 句点,匹配一个非换行符的字符。
* 星号,匹配零个或多个先前的字符或正则。
[] 匹配一个指定范围内的字符。如果字符集以 ^ 开头,匹配不再指定范围内的字符。
\(....\) 标记匹配字符,如"\(love\)",love被标记为 1。
\< 锚定单词的开始,如"\ 锚定单词的结束,如"grep\>" 匹配包含以grep结尾的单词的行。
x\{m\} 重复字符x,m次。如'0\{5\}' 匹配包含5个0的行。
x\{m,\} 重复字符x,至少m次。如'0\{5,\}' 匹配至少包含5个0的行。
x\{m,n\} 重复字符x,m到n次。如'0\{5,6\}' 匹配包含5-6个0的行。
\w 匹配文字或数字字符,也就是[A-Za-z0-9]。
\W \w的反置,[^A-Za-z0-9],匹配一个非单词字符,如句号等。
\b 单词锁定符,如 '\bgrep\b' 只匹配 grep。
用于egrep和grep -E 的元字符扩展集
+ 匹配一个或多个先前的字符或正则。
? 匹配零个或一个先前的字符。
a|b|c 匹配a或b或c。如 grep|sed 匹配grep或sed。
() 分组符号,如 love(able|rs)ov+ 匹配loveable或lovers,后面再匹配一个或多个ov。
x{m}, x{m,}, x{m,n} 作用同 x\{m\}, x\{m,\}, x\{m,n\} 。
欢迎关注我的微信公众号: coderbee笔记,可以更及时回复你的讨论。