Grep 是 Global Regular Expression Print 的缩写,它搜索指定文件的内容,匹配指定的模式,默认情况下输出匹配内容所在的行。注意,grep 只支持匹配而不能替换匹配到的内容。
基本语法语法格式:
grep [OPTIONS] PATTERN [FILE...]
grep [OPTIONS] [-e PATTERN | -f FILE] [FILE...]
grep 支持不同的匹配模式,比如默认的 BRE 模式,增强型的 ERE 模式,还有更强悍的 PRE 模式。普通情况下使用默认的 BRE(basic regular expression) 模式就可以了,这种方式的特点是支持的正则表达式语法有限。如果需要更进一步的正则表达式语法支持,可以使用 ERE(extended regular expression) 模式。如果要使用复杂的正则表达式语法,可以使用 PRE 模式,它支持 Perl 语言的正则表达式语法。
常用选项:
--help
-V, --version
-G, --basic-regexp BRE 模式,也是默认的模式
-E, --extended-regexp ERE 模式
-P, --perl-regexp PRE 模式
-F, --fixed-strings 指定的模式被解释为字符串
-i 忽略大小写
-o 只输出匹配到的部分(而不是整个行)
-v 反向选择,即输出没有没有匹配的行
-c 计算找到的符号行的次数
-n 顺便输出行号
递归目录中的所有文件
默认情况下 grep 会匹配指定定文件中的内容,如果我们指定了一个目录,grep 则直接罢工:
使用选项 -R, -r, --recursive 会递归指定目录下的所有文件,并匹配其内容:
$ grep -r 'world' ~/projects/
通过 -d recurse 选项可以实现同样的功能:
$ grep 'world' -d recurse ~/projects/
在递归的过程中只输出匹配内容所在的文件名称
如果我们只想查看匹配到的内容所在文件的名称,可以同时使用 r 和 -l, --files-with-matches 选项:
$ grep -rl email /home/nick/projects/bash/.git
在递归的过程中排除某些目录
可以在应用选项 r 的同时应用 --exclude-dir 选项来排除一些目录(注意,这里设置的也是正则表达式):
$ grep -r --exclude-dir='.git' 'email' .
还可以同时指定多个表达式:
$ grep -r --exclude-dir={.git,xgit} 'email' .
在递归的过程中排除指定的文件
可以在应用选项 r 的同时应用 --exclude 选项来排除一些文件(注意,这里采用的是 GLOB模式):
$ grep -r --exclude=*.txt 'email' .
不区分大小写
Grep 默认的匹配规则区分字符的大小写,使用选项 -i (小写字母i), --ignore-case 会在匹配中忽略字符大小写:
$ grep -i 'hello' email1
只输出匹配到的部分(而不是整个行)
Grep 默认会输出匹配到的内容所在的整个行,使用选项 -o, --only-matching 则只输出匹配到的内容:
$ echo "abc 123 test" | grep -o '[0-9]\{1,3\}'
输出的结果为:123
在需要把匹配的内容存入变量时 -o 选项非常有用,比如下面的示例把从文件中匹配到的 IP 地址保存在变量 ip 中:
ip=$(grep -o '[0-9]\{1,3\}\.[0-9]\{1,3\}\.[0-9]\{1,3\}\.[0-9]\{1,3\}' file.log) if test -z "${ip}"; then exit 1 fi echo ${ip}
把匹配条件当成一个字符串
有时候我们想要匹配一个固定的字符串,但是其中包含了特殊字符,比如:
$ grep '.*' email1.txt
这样的条件会返回文件中的每一行内容,这不是我们想要的。可以通过转义符来解决这个问题:
$ grep '\.\*' email1.txt
当然,我们还可以通过选项 F 来优美的解决这个问题,此时指定的条件会被当成一个字符串来匹配:
$ grep -F '.*' email1.txt