首页 > 技术文章 > grep Pocket Reference读记

hellogc 2013-07-27 15:48 原文

1 简介


grep的基本命令格式如下:
          grep [options] [regexp] [filename]
 
如果regexp中含有空格,应该使用单引号或双引号括起来。单引号和双引号的区别在于在双引号中可以使用SHELL变量。
 
有很多不同风格的正则表达式,但实际上它们都非常相近,下面介绍grep中使用的正则表达式。
表1 正则表达式元字符
元字符 元字符名称 匹配
匹配单个字符的元字符    
. Dot 任意一个字符
[...] Character class 方括号中列出的作意一个字符
[^...] Negated character class 任意一个方括号中没有列出的字符
\char Escape character 转义字符(The character after the slash literally.),用于查找元字符,比如要查找"$"符号,表达式为"\$"
匹配一个位置的元字符    
^ Caret 行首
$ Dollar sign 行尾
\< Backslash less-than 字首(Start of a word)
\> Backslash greater-than 字尾(End of a word)
量词    
? Question mark(extended regular expressions) 0个或1个
* Asterisk 0个或多个
+ Plus(extended regular expressions) 1个或多个
{N} Match exactly(extended regular expressions) 匹配N次
{N,} Match at least(extended regular expressions) 至少匹配N次
{min,max} Specified range(extended regular expressions) 匹配min到max次
其它    
| Alternation(extended regular expressions) Matches either expression given
- Dash 指出一个范围,如a-z
(...) Parentheses(extended regular expressions) Used to limit scope of alternation
\1,\2, ... Backreference Matches text previously matched within parentheses (e.g., first set, second set, etc.)
\b Word boundary Batches characters that typically mark the end of a word (e.g., space, period, etc.)
\B Backslash 同'\\'
\w Word character This is used to match any “word” character(i.e., any letter, number, and the underscore character)
\W Non-word character This matches any character that isn’t used in words (i.e., not a letter, number, or underscore)
\` Start of buffer Matches the start of a buffer sent to grep
\' End of buffer Matches the end of a buffer sent to grep
 
表2 POSIX定义的Character Class
定义 匹配的内容
[:alpha:] 字母,无论大小写
[:digit:] 数字
[:alnum:] 字母和数字
[:blank:] Space or tab characters(空格或制表)
[:xdigit:] 十六进制字符,包括数字、A-F和a-f
[:punct:] Any punctuation symbol(标点)
[:print:] 可打印字符(非控制字符)
[:space:] Any whitespace character
[:graph:] Exclude whitespace characters
[:upper:] 大写字母
[:lower:] 小写字母
[:cntrl:] 控制字符
 
正则表达式可以使用和C字符串常量一样的连接方式。下面是一个例子:
     'username:' `whoami` ' and home directory is ' "$HOME"
如果当前用户为sw,则上面的表达式匹配"username:sw and home directory is /home/sw"。
 
grep由4个不同的程序组成,它们使用不同的表达式模型并且各有优缺点:
  • Basic Regular Expressions (grep or grep -G)
  • Extended Regular Expressions (egrep or grep -E)
  • Fixed Strings (fgrep or grep -F)
  • Perl-Style Regular Expressions (grep -P)
 
2 Basic Regular Expressions (grep or grep -G)

grep命令提供了很多选项用于控制匹配方式和输出方式,下面列出这些选项并做简短解释。


表3 grep命令选项
选项 示例 说明
Match Control    
-e pattern, --regexp=pattern grep -e -style doc.txt 把pattern当前正则表达式来解释。示例中如果不加-e,-style会被解释为命令选项。
-f file, --file=file grep -f pattern.txt searchhere.txt 从指定文件中读取正则表达式。The pattern file must list one pattern per line.
-i, --ignore-case grep -i 'help' me.txt 忽略大小写。
-v, --invert-match grep -v oranges filename 返回那些不匹配的行。
-w, --word-regexp grep -w 'xyz' filename 匹配单词。示例等同于grep "\bxyz\b" filename
-x, --line-regexp grep -x 'Hello, world!' filename 匹配整行。示例等同于grep '^Hello, world!$' filename
General Output Control    
-c, --count grep -c contact.html access.log 输出匹配的行数,而不是匹配的行的内容。
--color[=WHEN],
--colour[=WHEN]
rep --color[=auto] regexp filename 如果终端支持,grep将对输出内容着色,着色方式由环境变量GREP_COLORS定义。WHEN有3个合法值:never, always和auto。
-l, --files-with-matches grep -l "ERROR:" *.log 只输出含有匹配内容的文件名。使用lazy matching,找到第1个匹配的行以后停止在当前文件的匹配。
-L, --files-without-match grep -L 'ERROR:' *.log 只输出不含有匹配内容的文件名。使用lazy matching。
-m NUM, --max-count=NUM grep -m 10 'ERROR:' *.log 匹配NUM行以后停止在当前文件的匹配。
-o, --only-matching grep -o pattern filename 只输出匹配的内容而不是匹配的行。在二进制文件中查找某个串时很有用,因为如果输出行的话,输出内容中的二进制内容可能导致终端错误。
-q, --quiet, --silent grep -q pattern filename 不输出内容。可能通过检查grep命令的返回值来判断匹配的结果。0表示有内容匹配,1表示没有匹配到,2表示出错。
-s, --no-messages grep -s pattern filename 忽略由于文件不存在和权限原因导致的出错,不输出相应的错误信息。
Output Line Prefix Control    
-b, --byte-offset grep -b pattern filename 输出匹配内容在文件中的偏移量,从0开始。由于默认输出的是匹配的行,因此偏移量是行首在文件中的偏移量。和-o选项一起使用可以得到匹配内容的准确偏移量。这个选项在进行二进制文件分析时有用。
-H, --with-filename grep -H pattern filename 输出文件名。在多个文件中搜索时这是默认设置。要注意文件名是相对路径。
-h, --no-filename grep -h pattern * 不输出文件名。
--label=LABEL gzip -cd file.gz | grep --label=LABEL pattern 将来自标准输入的内容视为来自文件LABEL,因此输出时如果显示文件名则显示为LABEL。
-n, --line-number grep -n pattern filename 显示匹配的行在文件中的行号,行号从1开始。
-T, --initial-tab grep -T pattern filename 在grep产生的前缀和匹配的内容之间添加一个TAB进行分隔。
-u, --unix-byte-offsets grep -u -b pattern filename 使用Unix方式计算偏移量,这将忽略Windows上常用的CR字符。
-Z, --null grep -Z pattern filename 在输出的文件名后面打印ASCII NULL字符而不是通常紧跟在文件名后的字符(比如使用-l选项时文件名后面默认会打印一个换行符),这有利于在脚本里面对包含特定串的文件进行处理。
Context Line Control    
-A NUM, --after-context=NUM grep -A 3 Copyright filename 除匹配行外,打印出匹配行后面的NUM行,每一组之间用"--"分隔。
-B NUM, --before-context=NUM grep -B 3 Copyright filename 打印出匹配行前面的NUM行。
-C NUM, -NUM, --context=NUM grep -C 3 Copyright filename 打印出匹配行前后的NUM行,与同时使用-A和-B选项效果相同。
File and Directory Selection    
-a, --text grep -a pattern filename 与选项 --binary-files=text相同,把一个二进制文件当作为文本文件进行处理。
--binary-files=TYPE grep --binary-files=TYPE pattern filename TYPE可以是binary, without-match或者text。默认情况下grep如果处理一个二进制文件并且包含指定的表达式,只会显示类似“Binary file somefile.bin matches”的信息,不会显示匹配的行。这与--binary-files=binary的行为相同。如何TYPE为without-match,则grep直接跳过二进制文件,不对其做任何处理。
-D ACTION, --devices=ACTION grep -D read 123-45-6789 /dev/hda1 如果输入文件是一个特殊文件如FIFO或套接字,-D选项指定grep如何对其进行操作。当ACTION为skip时,grep直接跳过相应文件;为read时,grep将从中读取内容就如同处理普通文件一样。
-d ACTION, --directories=ACTION grep -d ACTION pattern path 如果输入文件是一个目录,-d选项指定grep将如何对其进行操作。当ACTION为skip时,grep忽略相应文件;为read时,grep将其当作普通文件读取其内容;为recurse时,grep递归地处理其中的文件,与“-R”的行为相同。
--exclude=GLOB grep --exclude=PATTERN path 排除文件名匹配PATTERN的文件,可以使用SHELL通配符。
--exclude-from=FILE grep --exclude-from=FILE path 与--exclude效果相同,不同的是从文件FILE中读取PATTERN。文件中每行一个PATTERN。
--exclude-dir=DIR grep --exclude-dir=DIR pattern path 与--exclude效果相似,不同的是此选项作用于目录。
-I grep -I pattern filename 与 --binary-files=without-match效果相同。
--include=GLOB grep --include=*.log pattern filename 只处理文件名匹配GLOB的文件。
-R, -r, --recursive grep -R pattern path
grep -r pattern path
递归处理指定路径中的所有文件。
Other Options    
--mmap grep --mmap pattern filename 使用mmap()替代read(),可以提高性能。但是如果在处理的过程中文件发生收缩(shrink),则会导致错误。
-V, --version   显示grep的版本信息。
-z, --null-data grep -z pattern 将输入的内容视为以ASCII NULL字符结尾,而不是换行符。与-Z选项,不过是作用于输入而不是输出。
 
grep不能使用扩展的元字符的功能,包括?, +, {n,m}, |, (). 如果要在grep中获得这些元字符提供的功能,需要在前面加上"\"转义符,如grep 'behaviou\?r', 与egrep 'behaviou?r'相同。在这种情况下,转义字符的意义和通常的“转义”相反,容易混淆,最好直接使用egrep或grep -E。
 
3 Extended Regular Expressions (egrep or grep -E)

grep -E具有和grep相同的命令行选项,只是增加了一些元字符以创建更复杂和精确的表达式。grep -E支持以下grep不支持的元字符:?, +, {n,m}, |, ().
 
表4 Extended Regular Expressions支持的元字符
元字符 意义 示例
? 表示可选,即出现0次或1次 egrep 'behaviou?r' filename                   匹配behavior和behaviour
+ 表示出现1次或多次 egrep 'pattern1+' filename                    匹配pattern1, pattern11, pattern111....
{n,m} 表示至少出现n次,最多出现m次 egrep 'pattern{4}' filename                   匹配patternnnn
egrep 'pattern{4,}' filename                  n至少出现4次
egrep 'pattern{,4}' filename                  这种形式是错误的,不提供”最多出现X次”的语义
egrep 'pattern{4,6}' filename                n出现4次到6次
| 表示“或” egrep 'name1|name2' filename             匹配name1或者name2
( ) 将模式串分组(group)以便backreferences, alternation或者仅仅是为了提高可读性。
加上括号可以使得模式更准确和易理解,括号中的模式通常称为子模式(subpattern)。
括号还用于限制"|"元字符作用的边界。
egrep 'patt(a|e)rn' filename                  匹配pattarn或pattern
 
如果要使用egrep匹配字符'{',需要使用'[{]'进行转义,而不是'\{'。
 
4 Fixed Strings (fgrep or grep -F)

fgrep也被称为fast grep,因为它不使用正则表达式。使用方式:
     fgrep string_pattern filename
 
表5 fgrep支持的选项
选项 示例 说明
-b fgrep -b string_pattern filename 输出匹配的行的行首在文件中的偏移量
-c fgrep -c string_pattern filename 输出匹配的行数
-e, -string fgrep -e string_pattern1 -e string_pattern2 filename 将-e后面的串当作patter,用于指定多个模式,或者用于以'-'字符开头的模式
-h fgrep -h string_pattern filename 在多个文件中搜索时,结果不输出文件名
-i fgrep -i string_pattern filename 不区分大小写
-l fgrep -l string_pattern filename 输出匹配的文件名,但不输出匹配的行
-n fgrep -n string_pattern filename 输出行号,从1开始
-v fgrep -v string_pattern filename 输出不匹配的行
 
5 Perl-Style Regular Expressions (grep -P)

grep -P使用Perl-Compatible Regular Expressions (PCRE) library来解析正则表达式,Perl正则表达式擅长处理文本,但是也非常复杂,容易出错。grep -P的行为与系统中libpcre库和Perl的版本有关。另外,也不是所有版本的grep都支持-P选项。Red Hat系的系统一般都支持,而Debian默认不支持,但是会提供一个pcregrep来替代grep -P。
 
与grep -E和grep -F不同,grep -P没有pgrep命令。pgrep是用来查找系统中运行进程的命令。
 
所有grep的选项都可以用于grep -P,只是正则表达式的处理方式不同。
 
PCRE比较繁杂的样子,此处略。
 
6 grep相关的环境变量

grep的行为与系统的locale相关变量设置有关。通常情况下系统默认的locale设置就ok。
 
可以通过GREP_OPTIONS变量设置grep的默认行为。GREP_OPTIONS包含grep的命令行选项,因此要注意这些选项是不能被后续的命令行选项覆盖的,如果后续的命令行选项与GREP_OPTIONS中的冲突,则grep报错。
 
通过指定GREP_COLORS选项定制grep的输出配色方案。
 
7 grep的高级用法

使用alternation和backreference会导致性能低下,尤其是backreference可能导致grep所需时间呈指数级增长。
 
使用strings命令可以列出一个二进制文件中所有的字符串,如strings /bin/ls
 

推荐阅读