Grep 是 Global Regular Expression Print 的缩写。
它搜索指定文件的内容,匹配指定的模式,默认情况下输出匹配内容所在的行。注意,grep 只支持匹配而不能替换匹配到的内容。
基本语法
语法格式:
grep [OPTIONS] PATTERN [FILE1 FILE2 ...]
grep [OPTIONS] [-e PATTERN | -f FILE1] [FILE2 ...]
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 指定的模式被解释为字符串
-f, --file=FILE 从文件中读取正则表达式 -i 忽略大小写 -o 只输出匹配到的部分(而不是整个行) -v 反向选择,即输出没有没有匹配的行 -c 计算找到的匹配行的次数 -n 顺便输出行号
BRE正则表达式:
需要注意的是,在基本正则表达式(BRE)中,如+、{、|、( 和 )等,已经失去了它们原本的含义,而若要恢复它们原本的含义,则要在之前添加反斜杠 ,如 +、{、|、( 和 )。
如果表达式中包含特殊字符,最好使用双引号将表达式包起来,否则会有异常,当然如果是单纯的普通字符串,则不需要
与 BRE 相比 ERE 最大的优点是支持更多的元字符,也就是在使用这些字符时不需要 了。比如 BRE 中使用的 符可以全部去掉。
语法 | 说明 | 解释 |
. | 匹配一个任意的字符 | 在 [] 中 . 号并不是元字符 |
^ | 行的起始 | ^ 和 $ 匹配的是一个位置而不是具体的文本 |
$ | 行的结束 | ^ 和 $ 匹配的是一个位置而不是具体的文本 |
* | 匹配 0 次或多次 | 不匹配上一次表达式,匹配上一次或匹配多次,并生成所有可能的匹配 匹配尽可能多的次数,如果实在无法匹配,也不要紧 |
[] | 匹配若干个字符之一 | 又叫字符组、字符类,比如 [0-9]、[a-z]、[A-Z] 只有在字符组内部 - 才是元字符,表示一个范围 |
[^...] | 排除型字符组 | 字符组以 ^ 开头,它会匹配一个任何未列出的字符 |
? | 可选元素 | 在 BRE 中需要使用转义符 出现一次或者不出现 |
+ | 匹配 1 次或多次 | 在 BRE 中需要使用转义符 匹配前面表达式的至少一个搜索项 匹配尽可能多的次数,如果实在无法匹配,也不要紧 |
{min,max} | 量词区间 | 在 BRE 中需要使用转义符 |
| | 或(多选结构) | 在 BRE 中需要使用转义符 bob|nick 能够同时匹配其中任意一个的正则表达式,此时的子表达式被称为 "多选分支" 多选结构可以包括很多字符,但不能超越括号的界限 |
() | 分组 | 在 BRE 中需要使用转义符 括号能够 "记住" 它们包含的子表达式匹配的文本 反向引用(backreference)是正则表达式的特性之一,它允许我们匹配与表达式先前部分匹配的同样的文本 |
<> | 单词分界符 | 在 BRE 中需要使用转义符 < 和 > 本身并不是源字符,只有它们与反斜线结合时才具有单词分界符的含义 |
转义符 | 如果需要匹配的某个字符本身就是元字符,就需要使用转义符 | |
命名的字符类 | 命名的预定义字符类 | [[:upper:]] [A-Z] [[:lower:]] [a-z] [[:digit:]] [0-9] [[:alnum:]] [0-9a-zA-Z] [[:space:]] 空格或 tab [[:alpha:]] [a-zA-Z] |
[vagrant@localhost tasks]$ echo "aaaaabbbb" | grep "a{5}" //{ 和 }需要转义,否则不起作用,而是被当作普通的字符串 [vagrant@localhost tasks]$ echo "aaaaabbbb" | grep a{5} //包含特殊字符时如果不加引号,不起作用 [vagrant@localhost tasks]$ echo "aaaaabbbb" | grep "a{5}" //经过转义和使用双引号后,正常输出 aaaaabbbb
[vagrant@localhost tasks]$ echo "a{5}aaaabbbb" | grep a{5} // { 和 }不转义就会被当作普通的字符串
a{5}aaaabbbb
常见用例
text1.txt
text1 aaaaaa aaa bbbbbb ccccccc dddddd AAAAAA AAA aaabbb AAABBB aaabbb aaa bbb AAA bbb ccc text1
text2.txt
text2 aaaaaa aaa bbbbbb ccccccc dddddd AAAAAA AAA aaabbb AAABBB aaabbb aaa bbb AAA bbb ccc text2
1.搜索指定的单个文件中包含匹配模式的字符串的行
[vagrant@localhost tasks]$ grep "aaa" text1.txt //只搜索一个文件时,只输出匹配行,不输出文件名 aaaaaa aaa aaabbb aaabbb aaa bbb
2.搜索指定的多个文件中包含匹配模式的字符串的行
[vagrant@localhost tasks]$ grep "aaa" text1.txt text2.txt //搜索多个文件时,会在输出的匹配行内容前,同时输出文件名 text1.txt:aaaaaa text1.txt:aaa text1.txt:aaabbb text1.txt:aaabbb text1.txt:aaa bbb text2.txt:aaaaaa text2.txt:aaa text2.txt:aaabbb text2.txt:aaabbb text2.txt:aaa bbb
3.搜索指定的目录中所有文件中包含匹配模式的字符串的行
[vagrant@localhost tasks]$ grep "aaa" ./* //此处通配符*不可缺少,否则不起作用,如4例所示 grep: ./logs: Is a directory ./text1.txt:aaaaaa ./text1.txt:aaa ./text1.txt:aaabbb ./text1.txt:aaabbb ./text1.txt:aaa bbb ./text2.txt:aaaaaa ./text2.txt:aaa ./text2.txt:aaabbb ./text2.txt:aaabbb ./text2.txt:aaa bbb
4.递归目录中的所有文件
注意:默认情况下不能直接搜索目录,要想搜索某个目录中的所有文件,可以在目录后面加上通配符*,就如上面3的例子。如果向搜索指定目录中的所有文件,包括子目录中的文件,那么就需要选项 -R, -r, --recursive
如果我们只想查看匹配到的内容所在文件的名称,可以同时使用 r 和 -l
在递归的过程中排除某些目录,使用选项 --exclude-dir(注意,这里设置的也是正则表达式)
$ grep -r --exclude-dir='.git' 'email' $ grep -r --exclude-dir={.git,xgit} 'email'
在递归的过程中排除指定的文件,使用选项 --exclude
$ grep -r --exclude=*.txt 'email' .
[vagrant@localhost tasks]$ grep "aaa" ./ //只指定目录,默认不起作用 grep: ./: Is a directory [vagrant@localhost tasks]$ grep -r "aaa" ./ //使用选项-r,递归遍历所有目录中的文件,包括子目录中的文件 ./text1.txt:aaaaaa ./text1.txt:aaa ./text1.txt:aaabbb ./text1.txt:aaabbb ./text1.txt:aaa bbb ./text2.txt:aaaaaa ./text2.txt:aaa ./text2.txt:aaabbb ./text2.txt:aaabbb ./text2.txt:aaa bbb
[vagrant@localhost tasks]$ grep -rl "aaa" ./ //只想查看匹配到的内容所在文件的名称,使用选项-l
./text1.txt
./text2.txt
5.输出匹配行内容的同时,输出行号
[vagrant@localhost tasks]$ grep -n "aaa" text1.txt 2:aaaaaa 3:aaa 9:aaabbb 11:aaabbb 12:aaa bbb
6.搜索时忽略大小写,使用选项-i
[vagrant@localhost tasks]$ grep -i "aaa" text1.txt aaaaaa aaa AAAAAA AAA aaabbb AAABBB aaabbb aaa bbb AAA bbb ccc
7.前面说过,grep会默认输出包含匹配模式的字符串的整行,如果只想输出匹配的字符串而不输出整行,使用选项-o
[vagrant@localhost tasks]$ grep -o "aaa" text1.txt //只输出匹配的字符串而不输出整行 aaa aaa aaa aaa aaa aaa
8.当要搜索的内容包含特殊字符时(如正则中的通配符),需要转义或者选项-F
[vagrant@localhost tasks]$ (echo aaa; echo ".*"; echo bbb)|grep ".*" //".*"在正则中表示任意长度的字符串,所以全部输出,要想只输出".*",需要对特殊字符进行转义或者-F选项 aaa .* bbb [vagrant@localhost tasks]$ (echo aaa; echo ".*"; echo bbb)|grep ".*" //使用对特殊字符进行转义 .* [vagrant@localhost tasks]$ (echo aaa; echo ".*"; echo bbb)|grep -F ".*" //使用选项-F,把指定的条件会被当成一个字符串来匹配,而不是当作正则表达式 .*
9.统计匹配到的行的数量
[vagrant@localhost tasks]$ grep "aaa" text1.txt aaaaaa aaa aaabbb aaabbb aaa bbb [vagrant@localhost tasks]$ grep -c "aaa" text1.txt //使用选项-c后,不输出匹配的行内容,而是输出匹配行的行数统计 5
10.反转匹配条件
[vagrant@localhost tasks]$ grep -v "aaa" text1.txt //使用选项-v,不输出匹配的行内容,而是输出所有不匹配的行 text1 bbbbbb ccccccc dddddd AAAAAA AAA AAABBB AAA bbb ccc text1
11.从文件中读取正则表达式
如果正则表达式太长,或者是需要指定多个正则表达式,可以把它们放在文件中,然后使用 选项 -f FILE, --file=FILE 来指定这个文件。如果指定了多个正则表达式(每行一个),任何一个匹配到的结果都会被输出:
正则表达式文件pattern.txt,注意,文件中的正则表达式不能加引号,而且换行符要使用unix换行符
text1 a{3} ccc
[vagrant@localhost tasks]$ grep -f pattern.txt text1.txt //pattern.txt文件中的所有匹配模式的匹配行都输出
text1
aaaaaa
aaa
ccccccc
aaabbb
aaabbb
aaa bbb
AAA bbb ccc
text1
12.只匹配完整的行
如果我们只对一个完整的行感兴趣,可以使用选项 -x, --line-regexp。这样会忽略那些包含在行中的内容:
[vagrant@localhost tasks]$ grep "aaa" text1.txt aaaaaa aaa aaabbb aaabbb aaa bbb [vagrant@localhost tasks]$ grep -x "aaa" text1.txt //使用选项-x后,只有整行匹配时才会输出,如果匹配内容只是行内的一部分则不会输出 aaa
13.只匹配完整的单词(即匹配内容前后没有其他非空白字符),使用-w。-x为整行匹配,而-w为单词匹配
[vagrant@localhost tasks]$ grep -w "aaa" text1.txt //aaaaaa和aaabbb之类的没有输出,只输出了匹配内容前后没有其他非空白字符的行 aaa aaa bbb
grep还有很多其他的选项,这里就不一一举例了,可以通过 grep --help来查看
[vagrant@localhost tasks]$ grep --help Usage: grep [OPTION]... PATTERN [FILE]... Search for PATTERN in each FILE or standard input. PATTERN is, by default, a basic regular expression (BRE). Example: grep -i 'hello world' menu.h main.c Regexp selection and interpretation: -E, --extended-regexp PATTERN is an extended regular expression (ERE) -F, --fixed-strings PATTERN is a set of newline-separated fixed strings -G, --basic-regexp PATTERN is a basic regular expression (BRE) -P, --perl-regexp PATTERN is a Perl regular expression -e, --regexp=PATTERN use PATTERN for matching -f, --file=FILE obtain PATTERN from FILE -i, --ignore-case ignore case distinctions -w, --word-regexp force PATTERN to match only whole words -x, --line-regexp force PATTERN to match only whole lines -z, --null-data a data line ends in 0 byte, not newline Miscellaneous: -s, --no-messages suppress error messages -v, --invert-match select non-matching lines -V, --version display version information and exit --help display this help text and exit Output control: -m, --max-count=NUM stop after NUM matches -b, --byte-offset print the byte offset with output lines -n, --line-number print line number with output lines --line-buffered flush output on every line -H, --with-filename print the file name for each match -h, --no-filename suppress the file name prefix on output --label=LABEL use LABEL as the standard input file name prefix -o, --only-matching show only the part of a line matching PATTERN -q, --quiet, --silent suppress all normal output --binary-files=TYPE assume that binary files are TYPE; TYPE is 'binary', 'text', or 'without-match' -a, --text equivalent to --binary-files=text -I equivalent to --binary-files=without-match -d, --directories=ACTION how to handle directories; ACTION is 'read', 'recurse', or 'skip' -D, --devices=ACTION how to handle devices, FIFOs and sockets; ACTION is 'read' or 'skip' -r, --recursive like --directories=recurse -R, --dereference-recursive likewise, but follow all symlinks --include=FILE_PATTERN search only files that match FILE_PATTERN --exclude=FILE_PATTERN skip files and directories matching FILE_PATTERN --exclude-from=FILE skip files matching any file pattern from FILE --exclude-dir=PATTERN directories that match PATTERN will be skipped. -L, --files-without-match print only names of FILEs containing no match -l, --files-with-matches print only names of FILEs containing matches -c, --count print only a count of matching lines per FILE -T, --initial-tab make tabs line up (if needed) -Z, --null print 0 byte after FILE name Context control: -B, --before-context=NUM print NUM lines of leading context -A, --after-context=NUM print NUM lines of trailing context -C, --context=NUM print NUM lines of output context -NUM same as --context=NUM --group-separator=SEP use SEP as a group separator --no-group-separator use empty string as a group separator --color[=WHEN], --colour[=WHEN] use markers to highlight the matching strings; WHEN is 'always', 'never', or 'auto' -U, --binary do not strip CR characters at EOL (MSDOS/Windows) -u, --unix-byte-offsets report offsets as if CRs were not there (MSDOS/Windows) 'egrep' means 'grep -E'. 'fgrep' means 'grep -F'. Direct invocation as either 'egrep' or 'fgrep' is deprecated. When FILE is -, read standard input. With no FILE, read . if a command-line -r is given, - otherwise. If fewer than two FILEs are given, assume -h. Exit status is 0 if any line is selected, 1 otherwise; if any error occurs and -q is not given, the exit status is 2. Report bugs to: bug-grep@gnu.org GNU Grep home page: <http://www.gnu.org/software/grep/> General help using GNU software: <http://www.gnu.org/gethelp/>