grep 命令详解

grep 命令详解

概述:本文档基于 info grep 翻译,完成度可能 90% 左右。

作者:N10-guli

时间:2016-01-05

版本:v1.0

目录:

    1,grep 命令的选项

    2,grep 命令的正则表达式

    3,grep 命令使用示例

1,grep 命令的选项

1.1 概念

grep 从输入的文件中,寻找与 pattern list 匹配的行。
因为换行符也是 pattern list 的分隔符,所以不可能对换行符做匹配。

1.2 调用 grep 的语法

grep OPTIONS.. PATTERN INPUT_FILE_NAMES..

除了这种写法,pattern 也可以由 -e PATTERN 给出,或者从文件中读取 pattern -f FILE 。
省略号 .. 表示可以有多个

1.3 命令行选项

grep 命令有许多选项,来自 POSIX.2 和 GNU 的扩展。
长选项通常是 GNU 的扩展,短选项由 POSIX 指定。

1.3.1 普通的程序信息

--help 帮助

-V, --version 打印版本号

1.3.2 匹配控制

-e PATTERN, --regexp=PATTERN
可指定多个 PATTERN, 或用于保护以 - 开头的 PATTERN

-f FILE, --file=FILE
从 FILE 中获取 PATTERN, 一行为一个。空文件什么都不匹配。

-i, --ignore-case
忽略大小写

-v, --invert-match 
找出不匹配的行

-w, --word-regexp
整词匹配,匹配的字符串的前后不能是 字母,数字或下划线。

-x, --line-regexp 
整行匹配

1.3.3 总体输出控制

-c, --count
打印每个文件中匹配的行数

--color[=WHEN]
grep 结果的颜色控制,WHEN=never, always, auto
颜色由 GREP_COLORS 设置。

-L, --files-without-match
只打印没有匹配行的文件的文件名

-l, --files-with-matches
只打印有匹配行的文件的文件名

-m NUM, --max-count-NUM
匹配到了 NUM 行,就停止。
    while grep -m 1 PATTERN
    do
    echo xxxx
    done < FILE
这个脚本的含义是:在 FILE 中每匹配一行,执行一次 echo xxx。
与 -c 配合,输出必然小于等于 NUM
与 -v 配合,输出不匹配的行,最多 NUM 行。

-o, --only-mathing
只打印匹配的部分,而非整行

-q, --quit, --silent
如果有匹配的行,立即结束进程,返回 0 状态值,不输出任何信息。

-s, --no-messages
当遇到不存在的文件,或不可读的文件时,不打印错误。
为了脚本的可移植性,建议重定向标准输出和错误输出。

1.3.4 输出行的前缀控制

打印多个前缀字段时,顺序是固定的:文件名,行序号,字节偏移
以冒号':'分隔。

-b, --byte-offset
打印每一行的字节偏移(0-based)。
带了 -o 选项时,只计算匹配字符串的偏移。

-H, --with-filename
有多个文件输入时,默认带有 -H 选项。
在每一个匹配行之前,打印文件名前缀

-h, --no-filename
单个文件输入时,默认带有 -h 选项。
不打印文件名前缀。

--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-based)

-T, --initial-tab
使用 tab 使行尽可能对齐。

-u, --unix-byte-offsets
配合 -b 使用,使在 MS-DOW, MS-Windows 的输出与 Unix 环境相同

-Z, --null
在文件名后使用 zero byte(ASCII 的 NUL 字符)代替换行符
    grep -lZ FILE

输出的文件名以 nul 结尾。
配合 find -print0, sort -z, xargs -0, perl -0,
即使文件名含有特殊字符如 换行符,也能正确处理。

1.3.5 文本行控制

所有输入的行在输出中只会打印一次。相邻的输出有重合时,自动合并。
注意:以下的选项在使用 -o 选项后失效

-A NUM, --after-contex=NUM
打印匹配行以及其后的 NUM 行

-B NUM, --before-contex=NUM
打印匹配行以及其前的 NUM 行

-C NUM, -NUM, --contex=NUM
打印匹配行以及之前,之后的 NUM 行

--group-separator=STRING
-A, -B,—C 的输出,以 -- 分隔不同的组
这个选项可设置为以 STRING 分隔

--no-group-separator
不同的组,不做分隔

1.3.6 文件和目录选项

-a, --text
把二进制文件当做文本文件处理,有可能输出垃圾信息,产生边际效应。
(输出的信息被终端解释为其他命令)
等同于 --binary-files=text

--binary-files=TYPE
如果文件首部的字节指示这是一个二进制文件,当

TYPE=binary(默认值):
有匹配时,输出一条消息,说明匹配了
无匹配时,没有输出

TYPE=without-match:
假定没有匹配,与 -I 相同

TYPE=text
与 -a 相同,将其当做 文本文件处理

-D ACTION, --devices=ACTION
输入文件为 device, FIFO, socket 时。
使用 ACTION 处理。默认为 read, 正常读取。
如果为 skip, 这类文件被跳过,不做处理。

-d ACTION, --directories=ACTION
输入文件为 目录时,使用 ACTION 处理。
默认为 read, 将目录文件当做普通文件读取。
skip: 跳过
recurse: 目录下的文件都被递归地读取, 同于 -r 

--exclude=GLOB
GLOB 使用通配符匹配文件名:*, ?, [], [^],
\ 反斜线可以使通配符变为普通字符。
跳过匹配的文件名,不做处理

--exclude-from=FILE
从文件中读取要跳过的 GLOB

--exclude-dir=DIR
DIR 为 PATTERN
匹配的 dir 不做递归读取

-I 
二进制文件当做不匹配处理

--include=GLOB
只处理 GLOB 匹配的文件。
GLOB 是通配符

-r, -R, --recursive
命令行中的每一个目录,对其中的所有文件读取并处理,
其中还有目录的话,继续做递归处理。

1.3.7 其他选项

--line-bufferd
在输出时使用 line buffering

--mmap
读取输入时,使用 mmap 代替 read 函数

-U, --binary
仅在 MS-DOS, MS-Windows 有效。
grep 会通过文件 首部的32KB,猜测文件类型。
如果认为是 文本文件,会除去 CR 字符。

-U 会跳过猜测步骤而直接读取,这样遇到 CR/LF 结尾时可能使匹配出错

-z, --null-data
把输入的行看做以 NUL 结尾的行(正常是以 newline 结尾)进行处理。

1.4 环境变量

grep 的使用受到以下 环境变量 的影响
LC_FOO 类的变量与三个变量的值有关系,依次检查 LC_ALL, LC_FOO, LANG,
以第一个非空的变量值作为 LC_FOO 的值。如果都是空值,或者 locale 目录没有安装,
或者 grep 程序没有在编译时加入 国际语言 支持,这时就使用 C 作为变量值。

GREP_OPTIONS
指定默认选项,选项之间以空格分隔,默认选项放在显式给出的选项之前。
选项含有 \ 或者空格时,使用 \ 反斜线 转义空格和 \,

GREP_COLOR
已过时,但仍被支持
指定匹配部分的高亮颜色,默认为 01;31,加粗,红色前景色。

GREP_COLORS
指定输出的高亮颜色。
默认值为(以冒号作为分隔符)
ms=01;31:mc=01;31:sl=:cx=:fn=35:ln=32:bn=32:se=36
这部分太长,没有翻译了。

LC_ALL
LC_COLLATE
LANG
影响 [a-z] 的表示意义。

LC_ALL
LC_CTYPE
LANG
指定 字符类型。如,哪一个字符表示 空格。

LC_ALL
LC_MESSAGES
LANG
指定 grep 产生的消息使用的语言
默认为 C 表示使用美国英语。

POSIXLY_CORRECT
grep 的行为更符合 POSIX.2 的要求。
默认是 GNU 的风格。
POSIX.2 要求文件名后的 选项,被当做文件名看待,GNU 则将之重新排列,仍视为选项
POSIX.2 要求不能识别的选项被判断为 非法,GNU 则判断为 无效

_N_GNU_nonoption_argv_flags_
(N 为 grep 的进程 ID 号)
如果变量值的第 I 个字符为 1,则 grep 的第 I 个操作数将不被认为是 操作数。
用于防止文件名通配符的展开,被误认为选项。
此行为只在 GNU C library 支持下有效。
POSIXLY_CORRECT 禁用此选项。

1.5 退出状态值

正常情况下,如果有匹配的行,状态返回值为 0, 否则为 1。
有错误发生时,返回 2,除非带有 -q, 或 --quiet, 或 --silent 选项,并且有匹配的行。
Note, however, that POSIX only mandates, for programs such as
`grep', `cmp', and `diff', that the exit status in case of error be
greater than 1; it is therefore advisable, for the sake of portability,
to use logic that tests for this general condition instead of strict
equality with 2.

1.6 grep 程序

grep 从输入的文件中(- 或者没有输入文件名时,表示从标准输入中读取)
寻找与 PATTERN 匹配的行。
有四种不同的 grep 程序,由以下选项控制选取。

-G, --basic-regexp
以基本正则的语法解释 pattern。这是默认选项。

-E, --extended-regexp
以扩展正则的语法解释 pattern。

-F, --fixed-strings 
将 pattern 视为匹配固定的字符串,不同的 pattern 以 换行符分隔

-P, --perl-regexp
实验中的选项。以 Perl 正则的语法解释 pattern

egrep 等同于 grep -E 
fgrep 等同于 grep -F 
这两个命令已经过时,不建议使用。但仍被支持。

2,grep 的正则表达式

正则表达式通过一个 pattern 描述一组字符串。
grep 支持三种正则表达式:
1,基础正则,BRE
2,扩展正则,ERE
3,perl 正则

对于 GNU 的 grep,基础正则与扩展正则的功能没有区别。
在其他的实现中,基础正则的功能一般会弱一些。

以下的描述适用于 扩展正则,其与 基础正则的区别在后面会给出总结。
perl 正则提供更多功能,可参考 pcresyntax(3), pcrepattern(3) 的文档。
可能不适用于每一个系统。

2.1 基本结构

正则表达式基础的部分:单个字符的匹配。
大部分字符在正则表达式中代表其本身。
元字符是有特殊意义的字符,使用反斜线 \,可以使其失去特殊意义,代表其本身。
    
    .匹配任意单个字符
    
    ?此符号前面的字符可出现 0 次 或 1 次
    
    * 此符号前面的字符可出现 0 次 或 多次

    +此符号前面的字符可出现 1 次 或 多次

    {N} 此符号前面的字符刚好出现 N 次

    {N,} 此符号前面的字符出现 N+ 次

    {,M} 此符号前面的字符出现 0~M 次

    {N,M} 此符号前面的字符出现 N~M 次

两个正则表达式可以进行串联,最终匹配的字符串,由分别匹配两个
正则表达式的字符串连接而成。

两个正则表达式可以进行并联,EXPR | EXPR,表示匹配其中一个
重复的优先级高于串联,这两者的优先级又高于并联。
也可使用(),改变优先级关系,()中的表达式优先做处理。

2.2 字符分类和括号表达式

[LIST] 表示 LIST 字符列表中的任意一个
[^LIST] 表示 LIST 字符列表之外的任意一个
[0123456789] 表示任意一个数字

在默认的 C locale 中,[a-d] = [abcd]
在其他的 locale 中,[a-d] 可能等于 [aBbCcDd]
可设置 LC_ALL 为 C,保证是传统的解释 [a-d]=[abcd]。

以下是一些以名字分类的字符集,其解释依赖于 LC_CTYPE
以下是 LC_CTYPE=C 时的解释

大多数 元字符 在 [] 中失去其特殊含义,变为普通字符。
比较特殊的是 ']', '[]]' 匹配 ']' 字符,']' 必须放在中括号中的第一个位置

[:alnum:] 所有字母(包括大小写字母,下同)和数字
[:alpha:] 所有字母
[:blank:] 空格,制表符
[:digit:] 所有数字
[:graph:] 所有字母,数字,标点符号
[:lower:] 所有小写字母
[:upper:] 所有大写字母
[:print:] 所有字母,数字,标点符号,空格
[:punct:] 所有标点符号: ! " # $ % & ' ( ) * + , - . / : ; < = > ? @ [ \ ] ^ _ ` { | } ~
 
[:space:] 制表符,换行符,垂直制表符,跳页, 回车,空格
[:xdigit:] 16进制字符 0 1 2 3 4 5 6 7 8 9 A B C D E F a b c d e f

2.3 反斜线和特殊表达式

\b 匹配单词边缘的空字符串
\B 匹配非单词边缘的空字符串
\<匹配词首的空字符串
\>匹配词尾的空字符串
\w与 [[:alnum:]] 同义,匹配一个单词
\W与 [^[:alnum:]] 同义,匹配非单词字符组成的一个单词
\brat\b 匹配独立的单词 rat
\Brat\B 匹配 crate,不匹配 furry rat

2.4 锚定

^ 和 $ 是元字符,匹配行首和行尾的空字符串


2.5 反向引用和子表达式

\N,引用第 N 个() 匹配的内容。
(a)\1 匹配 aa

当使用 -e 或 -f 指定多个正则表达式,反向引用的有效范围限定于当前表达式

2.6 基本正则 vs 扩展正则

在基本正则中,?,+,{,},|,(,) 失去了特殊意义
使用:\?, \+, \{, \}, \|, \(, \)

传统的 egrep 不支持 { 元字符,有一些支持 \{ 元字符。
所以,可移植的脚本应该避免在调用 grep -E 时使用 { 元字符。

使用 [{] 可以使其失去特殊意义,匹配 { 字符 

GNU grep -E 支持传统的用法,如果 { 没有成对使用
grep -E '{1' 将会匹配 '{1' 字符串,而不是报错。
POSIX.2 允许这种扩展,但是为了可移植性,应避免使用。

3,grep 使用示例

1, 只输出有匹配的文件的文件名
    
    grep -l 'main' *.c
    
    列出含有 main 的 C 文件名

2,如何递归地搜索目录

    grep -r 'hello' /home/gigi

    进一步限定搜索范围,可以使用 find, xargs 配合 grep:

    find /home/gigi -name '*.c' -print0 | xargs -r0 grep -H 'hello'

    与之类似:

    grep -rH --include='*.c' 'hello' /home/gigi

    下面这条命令与上面的命令不同,它的搜索范围限于当前目录:

    grep -rH 'hello' *.c 

    
3,如果 pattern 以 - 开头怎么办?
    
    grep -e '--cut here --' *

    如果这里不加 -e,grep 尝试将 pattern 解释成一组选项

4,假如我想搜索整个单词,而不是单词的一个部分该如何做?

    grep -w 'hello' *

    这条命令不会匹配 Othello,只会匹配单独的单词 hello。

    使用 '\<' 和 '\>' 可以分别匹配词首和词尾,比如

    grep 'hello\>' *

    这会匹配以 hello 结尾的单词,比如 Othello。
    (做整词匹配的单词两旁相邻位置不应该有 数字,字母,下划线,这些被定义为单词成分)


5,查看匹配行前面的行和后面的行
    
    grep -C 2 'hello' *

6,在输出行加上文件名前缀
    
    加上 /dev/null
        grep 'sshd' /etc/passwd /dev/null

    GNU 中可以使用 -H:

    grep -H 'sshd' /etc/passwd


7,为什么在过滤 ps 的输出,会有奇怪的正则?
    
    ps -ef | grep '[c][/c]ron'
    
    如果不加 [],会输出 grep 进程那一行。

8,为什么 grep 报告 Binary file matches
    如果 grep 输出一个二进制文件的匹配行,一般是无用的信息。
    所以 grep 默认不输出匹配信息。
    强制输出,使用 --binary-files=text
    消除 "Binary file matches" 信息,使用:
    -I 或者 --binary-files=without-match

9,为什么 grep -lv 不打印没有匹配行的文件的文件名?
    grep -lv 列出含有一个或多个不匹配行的文件名,这个文件中可能还有匹配的行。
    
    列出没有匹配行的文件名,使用:
    grep -L 或者 
    grep --files-without-match

10,使用什么表示 and 关系
    grep 'paul' /etc/motd | grep 'franc,ois'
    调用两次 grep

11,如何同时从 标准输入和文件中读取
    使用特殊文件名 -
    cat /etc/passwd | grep 'alain' - /etc/motd

12,从 ifconfig 输出中抓取 ipv4 地址(添加的例子,仅供参考)

ifconfig | grep -E "([0-9]|2[0-4][0-9]|25[0-5]|[1-9][0-9]|1[0-9][0-9])\.([0-9]|2[0-4][0-9]|25[0-5]|[1-9][0-9]|1[0-9][0-9])\.([0-9]|2[0-4][0-9]|25[0-5]|[1-9][0-9]|1[0-9][0-9])\.([0-9]|2[0-4][0-9]|25[0-5]|[1-9][0-9]|1[0-9][0-9])"

原创文章,作者:guli3057,如若转载,请注明出处:http://www.178linux.com/10903

(1)
guli3057guli3057
上一篇 2016-02-14
下一篇 2016-02-14

相关推荐

  • 马哥教育网络班21期-第五周课程练习

    1、显示/boot/grub/grub.conf中以至少一个空白字符开头的行; [root@localhost ~]# grep "^[[:space:]]\{1,\}" /boot/grub/grub.conf 2、显示/etc/rc.d/rc.sysinit文件中以#开头,后面跟至少一个空白字符…

    Linux干货 2016-08-08
  • 不忘初心,砥砺前行!

    这是本人第一次书写博客,难免有些小心翼翼,手足无措,但每个人都有这样的经历,转念一想也就释怀了。时光飞速,我们已不再年轻,从大学毕业的那天起,我们就再也不是小孩子了。 7月的天气总是那么折磨人,高温让我们步履维艰,在7月只想找一片月淡风轻的乐土,度过一个难熬的夏天,或找一间空调房,调大音量,享受午后时光。但这样的日却离我们很远,这个夏天我们背起行囊,远离故土…

    2017-07-11
  • N22-第六周作业

    请详细总结vim编辑器的使用并完成以下练习题 单词间跳转 w:下一个单词的词首 e:当前或后一个单词的词尾 b:当前或前一个单词的词首 行首行尾跳转: ^:跳转至行首的第一个非空白字符 0:跳转至行首 $: 跳转至行尾 句间跳转: ) ( 段落跳转: } { 字符编辑 x:删除光标所在处的字符 #x:删除光标所在处起始的#个字符 xp:交换光标所在处的字符与…

    Linux干货 2016-09-26
  • Linux命令帮助及history命令的使用

    1.Linux命令帮助的获取详解 在Linux中获取命令帮助时,内部命令和外部命令的获取方式是有区别的: 即  (1)内部命令:#help COMMAND ?            #man bash  (2)外部命令:<1> # COMMAND –hel…

    Linux干货 2016-08-05
  • Linux网络配置基础二(网络模块与nmcli命令)

    Linux网络配置基础二 相关命令 lsmod命令 lsmod命令用于显示已经加载到内核中的模块的状态信息。执行lsmod命令后会列出所有已载入系统的模块。Linux操作系统的核心具有模块化的特性,应此在编译核心时,务须把全部的功能都放入核心。您可以将这些功能编译成一个个单独的模块,待需要时再分别载入。第一列:表示模块的名称第二列:表示模块的大小第三列:表示…

    Linux干货 2016-09-09
  • Linux 基础(6)—— 权限

    修改所属人,所属组                文件的 r w x 权限            修改文件的权限chmod          umask &nb…

    2017-07-27

评论列表(1条)

  • stanley
    stanley 2016-02-14 10:05

    分类清晰明了