Grep
Grep 是一个 Unix 实用程序,它搜索通过管道传递给它的信息,或当前目录中的文件。一个例子应该有助于澄清事情。
假设我们要搜索一个目录,并想找到所有名称中包含字符串 "hello" 的文件。你可能会在 shell 中发出 'ls' 命令来列出目录的内容,并
$ ls
DumpSite.sh crontab.txt nagios-3.0.6 xmpppy xymon-4.3.0-beta2
并手动查看所有内容,或者你可以使用 'ls' 命令并将 'ls' 的输出管道到 grep
$ ls |grep crontab
crontab.txt
相反,如果你想过滤一个列表,除非某些条目,将其放在参数 -v 中
$ ls |grep -v crontab
DumpSite.sh
nagios-3.0.6
xmpppy
xymon-4.3.0-beta2
'|' 字符是管道表示法,它基本上将 'ls' 命令的输出作为 grep 的输入。你应该会得到一个包含所有名称中包含 "hello" 的文件的列表(可能是空的)。
对于搜索词,grep 可以接受正则表达式,而不是普通字符串。一个简单的例子可能是查找目录中的所有 .txt 或 .jpg 文件
$ ls | grep '.*\(txt\|jpg\)'
这里的正则表达式由 .* 组成,它可以代表文件名中的任何内容,以及 \(txt\|jpg\) ,它产生 txt 或 jpg 作为文件扩展名。
grep 的命令行选项,又称开关
- -e 模式
- -i: 忽略大小写。
- -v: 反转匹配。
- -c: 只输出匹配行的数量。
- -l: 只输出匹配的文件。
- -n: 在每条匹配行之前加上行号。
- -b: 一个历史上的好奇现象:在每条匹配行之前加上块号。
- -h: 输出匹配行,但不要在它们前面加上文件名。
- -s: 抑制关于不存在或不可读文件的错误消息。
- -x
- -f 文件:从文件中获取正则表达式。
- -o: 输出匹配行中匹配的部分。
GNU grep 的命令行选项,又称开关,超越了基本的 grep
- --help
- -V, --version
- --regexp=模式,除了 -e 模式
- --invert-match,除了 -v
- --word-regexp,除了 -w
- --line-regexp,除了 -x
- -A 数值, --after-context=数值
- -B 数值, --before-context=数值
- -C 数值, -数值, --context=数值
- 等等...
链接
- 2.1 命令行选项 在 grep 手册,gnu.org
- Unix grep(1) 手册页 在 man.cat-v.org,DESCRIPTION 部分
Grep 使用一种特殊的正则表达式版本,不同于 sed 和 Perl。Grep 涵盖了 POSIX 基本正则表达式(另见 正则表达式/Posix 基本正则表达式)。
grep 中可用的正则表达式功能包括 *、.、^、$、[ ]、[^ ]、\( \)、\n、\{i\}、\{i,j\}、\{i,\}。
GNU grep 中可用的正则表达式功能,作为 GNU 扩展,包括 \?、\+、\b、\B、\<、\>、\w、\W、\s、\S。
grep 中带有 -E 开关可用的正则表达式功能包括 ?、+、|、( )、{i}、{i,j}、{i,}。
grep 支持的预定义字符类包括 [:alpha:]、[:blank:]、[:cntrl:]、[:digit:]、[:graph:]、[:lower:]、[:print:]、[:punct:]、[:space:]、[:upper:] 和 [:xdigit:]。
grep 中不可用的正则表达式功能包括 Perl 的 \d、\D、\A 和 \Z。
链接
- 正则表达式 在 GNU grep 手册,gnu.org
当从 find 调用 grep 时,让 grep 输出文件的完整路径,然后输出匹配的内容非常有用。为了做到这一点,让 grep 认为它是被多个文件调用的,在 {} 后面加上 /dev/null
,就像这样
find /var/www -exec grep php {} /dev/null \;
grep 使用的例子
echo file.txt | grep ".*\(txt\|doc\)"
- 匹配。"\(" 和 "\)" 创建一个组,而 "\|" 分隔组中的项目。如果至少有一个项目匹配,则该组匹配。
echo a456 | grep "[a-zA-Z][0-9][0-9]*"
- 匹配。 "[" 和 "]" 是字符组的定界符。 "*" 代表 0 个、1 个或任何其他数量的前面内容。
echo a456 | grep -i "[A-Z][0-9]\+"
- 匹配。"\+" 代表前面内容的 1 个或多个出现。与 "*" 不同,"+" 必须以 "\" 开头。"-i" 使搜索不区分大小写。
echo file.txt | grep -E ".*(txt|doc)"
- 匹配。"-E" 代表扩展正则表达式。在扩展正则表达式中,"(" 和 "|" 不需要 "\" 就可以充当特殊字符;它们需要 "\" 才能充当字面量,也就是说,代表它们自身。
echo abbc | grep -E "abb?c"
- 在 -E 开关启用的扩展正则表达式中,问号匹配前面内容的 0 个或 1 个出现。
echo abbc | grep "abb\?c"
- 在 GNU Grep 中,\?(反斜杠后面的问号)匹配前面内容的 0 个或 1 个出现。
echo a4c | grep -P "a\dc"
- 在某些版本的 GNU Grep 中,匹配。"-P" 代表 Perl 正则表达式;正则表达式中的 "\d" 代表一个数字。
grep -P "\x22hello\x22" file.txt
- 在某些版本的 GNU Grep 中,搜索以引号开头、接着是 "hello"、再接着是另一个引号的字符串。利用了 -P,它开启了 Perl 正则表达式。在 Perl 正则表达式中,"\x22" 代表引号,通过代表十六进制 ASCII 值为 22 的字符。
grep -P "a\t+b" file.txt
- 在某些版本的 GNU Grep 中,用 "\t" 表示制表符(制表符)。由 -P 启用。
grep -r "soughtPattern" . --include=*.java
- 在某些版本的 GNU Grep 中,递归地搜索文件。注意句点代表当前目录。
grep -Fxv -f file2.txt file1.txt
- 输出集合差:file1.txt - file2.txt。使用 -F 来按字面解释搜索词,即非正则表达式,-x 来仅匹配整行,-v 来反转匹配,-f 来从文件获取搜索词。
grep -Fx -f file1.txt file2.txt
- 输出集合交集:file1.txt 中也在 file2.txt 中出现的那些行。
grep -P "Sch\xc3\xb6nheit" *
- 在 unicode UTF-8 编码的文件中搜索德语单词 "Schönheit"。利用 -P 开启 Perl 正则表达式;使用 \x 后面跟着十六进制数来搜索 ö 的 UTF-8 编码,即 C3B6。要找出 UTF-8 文本的十六进制代码,使用一个支持 UTF-8 的纯文本编辑器创建一个包含该文本的文件,然后使用十六进制显示程序(在多个操作系统上都是 hexdump)来查找文本的十六进制代码。UTF-8 编码不要与代码点混淆;ö 的代码点是 F6,而它的 UTF-8 编码是 C3B6。
grep -a -i -o "[-_a-z0-9 ]\{4,\}" mybinary.o
- 在一定程度上模拟 strings 命令,输出至少 4 个字符长度的字符串序列,这些序列符合对允许字符串字符的特定标准。使用 -a 将二进制文件视为文本文件,使用 -o 只输出找到的匹配模式的序列,而不是包含匹配项的行。
nice -19 find /etc /var/www -type f -name "*.php" -exec grep -e foreach -e str_replace -e return.*base64_decode {} /dev/null \; >php-possible-malware.txt
- 然后用这个分析,它首先显示最长的行:
cat php-possible-malware.txt | awk '{ print length, $0 }' |sort -n -s -r |head -50 |less
- 然后用这个分析,它首先显示最长的行:
perl -ne "print if /\x22hello\x22/" file.txt
- 这不是真正的 grep 示例,而是一个 Perl 单行程序,如果 Perl 可用,而 grep 不可用,你可以使用它。
可以从 GNU ftp 服务器 获取旧版本的 GNU grep。
GNU grep 的发布公告在 savannah 组 中。
可以从 git.savannah.gnu.org 获取 GNU grep 的变更日志。
可以在 GnuWin32 项目 以及 Cygwin 中获得用于 MS Windows 的 GNU grep 版本。
- GNU grep 用户手册作为单页 在 gnu.org
- grep(1) OS X 手册页 在 developer.apple.com
- Unix grep(1) 手册页 在 man.cat-v.org
- 维基百科关于 grep 的文章