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

(0)
上一篇 2016-02-14 10:03
下一篇 2016-02-14 10:05

相关推荐

  • Linux发展史

    前言     Linux属于类Unix中的一个当下比较流行的操作系统,占领了服务器大部分江山。作为一个专业复杂的操作系统,了解其发展过程是很有必要的。如果要讲linux的历史,肯定是从三个团体开发Multics系统说起,贝尔实验室离开Multics项目后,Tompson和他的同事一起创造了unix,而在unix的各种分支中BSD则是迅速发…

    Linux干货 2016-10-14
  • 04用户和组的相关配置文件总结

    1、用户 个人理解的是,给使用者一个在系统中使用的身份,即用户。 用户分两种:管理员和普通用户。 而每一个用户都有一些属性,每一个属性都是用冒号分割开来。配置文件存储在【/etc/passwd】中。 例如,sarash:x:507:508::/home/sarash:/bin/nologin 他们分别是,用户名,密码,ID号,主组ID号,注释,家目录,默认登…

    Linux干货 2016-10-24
  • 马哥教育网络班20期+第5周课程练习

    1、显示/boot/grub/grub.conf中以至少一个空白字符开头的行; grep "^[[:space:]]\+.*" /boot/grub/grub.conf   2、显示/etc/rc.d/rc.sysinit文件中以#开头,后面跟至少一个空白字符,而后又有至少一个非空白字符的行; grep&nb…

    Linux干货 2016-07-12
  • shell中的引号用法

        SHELL引号  在shell里可以通过使用单引号,双引号,反引号(TAB键上方的按键),反斜线来转换某些shell元字符的含义。比如说,我们希望echo命令显示出$本身字符的意义,而不是变量,我们需要使用某些功能来屏蔽$符号本身赋予的特殊含义,使其还原本身字面的意思。 主要讲述四个比较特殊常用的符号。 1.反…

    2017-06-11
  • 第三周作业

    1、列出当前系统上所有已经登录的用户的用户名,注意:同一个用户登录多次,则只显示一次即可。     who | cut -d ' ' -f 1 | uniq 2、取出最后登录到当前系统的用户的相关信息。    egrep "^$(who | tail -1 | cut -d ' …

    Linux干货 2016-12-19
  • mysql基础

      mysql基础 数据模型: 数据模型:层次模型、网状模型、关系模型、…… 关系模型: 二维关系:表     行:row, entity     列:colume, attribution 索引:数据结构,辅助完成数据查找;  &nbsp…

    Linux干货 2016-11-01

评论列表(1条)

  • stanley
    stanley 2016-02-14 10:05

    分类清晰明了