文本过滤好帮手grep
写在开头
此篇详细讲解了如何使用grep命令搜索你关心的内容,学完此篇,你可以
- 知道grep是什么,能干什么
- 了解常用的grep选项
- 了解基本正则表达式,搭配grep对文本进行模式匹配
自我介绍
grep是文本搜索工具,它的作用是根据用户指定的“模式(过滤条件)”对目标文本逐行进行匹配检查,并打印匹配到的行。模式:由正则表达式的元字符及文本字符所编出的过滤条件。
这里的目标文本,有两处:
- 标准输入
- 文件
在给出文件或标准输入后,grep会对匹配一个或多个正则表达式的文本进行搜索,并只输出匹配(或者不匹配)的行或文本。
初露身手
如果还没接触正则表达式,不要害怕,稍后会详细介绍。这里只利用grep搜索完整的keyWord关键字。
目标文本:文件
示例:在/etc/fstab下搜索UUID关键字
#( 06/07/18@12:37上午 )( root@centos7 ):~/mysh
cat /etc/fstab
#
# /etc/fstab
# Created by anaconda on Fri Aug 18 03:51:14 2017
#
# Accessible filesystems, by reference, are maintained under '/dev/disk'
# See man pages fstab(5), findfs(8), mount(8) and/or blkid(8) for more info
#
UUID=59d9ca7b-4f39-4c0c-9334-c56c182076b5 / ext4 defaults 1 1
#( 06/07/18@12:38上午 )( root@centos7 ):~/mysh
grep "UUID" /etc/fstab
UUID=59d9ca7b-4f39-4c0c-9334-c56c182076b5 / ext4 defaults 1 1
#( 06/07/18@12:38上午 )( root@centos7 ):~/mysh
grep 'UUID' /etc/fstab
UUID=59d9ca7b-4f39-4c0c-9334-c56c182076b5 / ext4 defaults 1 1
#( 06/07/18@12:38上午 )( root@centos7 ):~/mysh
grep UUID /etc/fstab
UUID=59d9ca7b-4f39-4c0c-9334-c56c182076b5 / ext4 defaults 1 1
目标文本:标准输入
示例: 搜索/目录下是否存在bin目录(管道)
#( 06/07/18@12:43上午 )( root@centos7 ):~
ls /
backups bin boot dev etc home lib lib64 lost+found media mnt opt proc root run sbin srv sys tmp users usr var
#( 06/07/18@12:43上午 )( root@centos7 ):~
ls / | grep "bin"
bin
sbin
#( 06/07/18@12:43上午 )( root@centos7 ):~
ls / | grep 'bin'
bin
sbin
#( 06/07/18@12:43上午 )( root@centos7 ):~
ls / | grep bin
bin
sbin
示例:在test.txt中搜索fefora(输入重定向)
#( 06/07/18@ 1:02上午 )( root@centos7 ):/tmp/workspace
cat test.txt
fedora is one of red hat
CentOS is One of Red Hat
Ubantu is One of Debian
#( 06/07/18@ 1:02上午 )( root@centos7 ):/tmp/workspace
grep "fedora" < test.txt
fedora is one of red hat
正如grep自我介绍中所说,根据用户指定的“模式(过滤条件)”对目标文本逐行进行匹配检查,并打印匹配到的行。只要匹配到keyWord就打印出这一行。
然而grep可不只是这么简单。
功能选项
具体用法:
#( 06/07/18@ 1:17上午 )( root@centos7 ):/tmp/workspace
grep --help
用法: grep [选项]... PATTERN [FILE]...
在每个 FILE 或是标准输入中查找 PATTERN。
默认的 PATTERN 是一个基本正则表达式(缩写为 BRE)。
例如: grep -i 'hello world' menu.h main.c
正则表达式选择与解释:
-E, --extended-regexp PATTERN 是一个可扩展的正则表达式(缩写为 ERE)
-F, --fixed-strings PATTERN 是一组由断行符分隔的定长字符串。
-G, --basic-regexp PATTERN 是一个基本正则表达式(缩写为 BRE)
-P, --perl-regexp PATTERN 是一个 Perl 正则表达式
-e, --regexp=PATTERN 用 PATTERN 来进行匹配操作
-f, --file=FILE 从 FILE 中取得 PATTERN
-i, --ignore-case 忽略大小写
-w, --word-regexp 强制 PATTERN 仅完全匹配字词
-x, --line-regexp 强制 PATTERN 仅完全匹配一行
-z, --null-data 一个 0 字节的数据行,但不是空行
输出控制:
-m, --max-count=NUM NUM 次匹配后停止
-b, --byte-offset 输出的同时打印字节偏移
-n, --line-number 输出的同时打印行号
--line-buffered 每行输出清空
-H, --with-filename 为每一匹配项打印文件名
-h, --no-filename 输出时不显示文件名前缀
--label=LABEL 将LABEL 作为标准输入文件名前缀
-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
文件控制:
-B, --before-context=NUM 打印以文本起始的NUM 行
-A, --after-context=NUM 打印以文本结尾的NUM 行
-C, --context=NUM 打印输出文本NUM 行
常用选项
–color=auto:对匹配到的文本着色后高亮显示(grep别名默认选项)
-i:ignorecase,忽略字符的大小写
#( 06/07/18@ 1:06上午 )( root@centos7 ):/tmp/workspace
cat test.txt
fedora is one of red hat
CentOS is One of Red Hat
Ubantu is One of Debian
#( 06/07/18@ 1:06上午 )( root@centos7 ):/tmp/workspace
grep centos test.txt
#( 06/07/18@ 1:06上午 )( root@centos7 ):/tmp/workspace
grep -i centos test.txt
CentOS is One of Red Hat
-o:仅显示匹配到的字符串本身
#( 06/07/18@ 1:06上午 )( root@centos7 ):/tmp/workspace
cat test.txt
fedora is one of red hat
CentOS is One of Red Hat
Ubantu is One of Debian
#( 06/07/18@ 1:06上午 )( root@centos7 ):/tmp/workspace
grep -o fedora test.txt
fedora
-v,—invert-match:显示不能被模式匹配到的行
#( 06/07/18@ 1:06上午 )( root@centos7 ):/tmp/workspace
cat test.txt
fedora is one of red hat
CentOS is One of Red Hat
Ubantu is One of Debian
#( 06/07/18@ 1:08上午 )( root@centos7 ):/tmp/workspace
grep -v fedora test.txt
CentOS is One of Red Hat
Ubantu is One of Debian
-q,—quiet,—slient:静默模式,即不输出任何信息
#( 06/07/18@ 1:06上午 )( root@centos7 ):/tmp/workspace
cat test.txt
fedora is one of red hat
CentOS is One of Red Hat
Ubantu is One of Debian
#( 06/07/18@ 1:09上午 )( root@centos7 ):/tmp/workspace
grep -q fedora test.txt
#( 06/07/18@ 1:10上午 )( root@centos7 ):/tmp/workspace
echo $?
0
#( 06/07/18@ 1:11上午 )( root@centos7 ):/tmp/workspace
grep -q aaaaa test.txt
#( 06/07/18@ 1:11上午 )( root@centos7 ):/tmp/workspace
echo $?
1
'注意':$?是命令执行结果状态返回值,0代表真,非0代表假
-A NUM:after,后NUM行
-B NUM:before,前NUM行
-C NUM:前后各NUM行
#( 06/07/18@ 1:11上午 )( root@centos7 ):/tmp/workspace
grep -A1 fedora test.txt
fedora is one of red hat
CentOS is One of Red Hat
#( 06/07/18@ 1:15上午 )( root@centos7 ):/tmp/workspace
grep -i -A1 centos test.txt
CentOS is One of Red Hat
Ubantu is One of Debian
#( 06/07/18@ 1:17上午 )( root@centos7 ):/tmp/workspace
grep -i -B1 centos test.txt
fedora is one of red hat
CentOS is One of Red Hat
#( 06/07/18@ 1:17上午 )( root@centos7 ):/tmp/workspace
grep -i -C1 centos test.txt
fedora is one of red hat
CentOS is One of Red Hat
Ubantu is One of Debian
grep的左膀右臂:正则表达式
what is 正则
正则表达式(英语:Regular Expression,在代码中常简写为regex、regexp或RE)。一个正则表达式通常被称为一个模式(pattern),为用来描述或者匹配一系列匹配某个句法规则的字符串。
这里所讲正则表达式不代表正则的所有模式,但基本满足我们运用它结合grep来对文本进行“模式”过滤。
元字符
* 字符匹配
. :匹配任意单个字符
[] :匹配范围内字符
[\^] :取反范围内字符
* 匹配次数
* :匹配次数
\? :匹配0次或者1次
\+ :至少匹配1次
\(m,n\):匹配(m,n)次
* 位置锚定
^ :行首锚定:用于模式的最左侧
$ :行尾锚定:用于模式最右侧
^PATTERN$ :匹配整行
^$ :空白行
^[[:space:]]*$ :空行或包含空白字符的行
单词 :非特殊字符组成的连续字符(字符串)都称为单词
\< 或 \b:词首
\> 或 \b:词尾
\<PATTERN\>:匹配完整单词
* 分组及引用
\( \):将一个或多个字符绑在一起,当做一个整体进行处理
注意:分组括号中的模式匹配到的内容会被正则表达式引擎自动记录于内部的变量中,这些变量为:
\1:模式从左侧其,第一个左括号以及与之匹配的右括号之间的模式所匹配到的字符
\2
\3
….
正则与grep
grep 结合正则表达式能做很多优美的事情。
示例:
#示例文件内容
#( 06/07/18@11:27下午 )( root@centos7 ):/tmp/workspace
cat test.txt
fedora is one of red hat
CentOS is One of Red Hat
Ubantu is One of Debian
#1. 元字符.匹配任意单个字符
#( 06/07/18@11:27下午 )( root@centos7 ):/tmp/workspace
cat test.txt | grep "f..o"
fedora is one of red hat
#2. 元字符.*组合匹配f ~ e
#( 06/07/18@11:42下午 )( root@centos7 ):/tmp/workspace
cat test.txt | grep "f.*e"
fedora is one of red hat
CentOS is One of Red Hat
Ubantu is One of Debian
#3. 元字符[]匹配范围内字符
#( 06/07/18@11:42下午 )( root@centos7 ):/tmp/workspace
cat test.txt | grep "[fCU].*f"
fedora is one of red hat
CentOS is One of Red Hat
Ubantu is One of Debian
#4. 元字符[^]结合行首锚定^匹配行首不是某些字符
#( 06/07/18@11:47下午 )( root@centos7 ):/tmp/workspace
cat test.txt | grep "^[^fC].*f"
Ubantu is One of Debian
grep还可以将规则(模式)定义在一个文件中,通过读取文件来匹配标准输入。
示例:
#1.从文件中读取规则,并过滤文本内容
#( 06/10/18@10:16上午 )( root@centos7 ):/tmp/workspace
cat rule.txt
centos
redhat
#( 06/10/18@10:16上午 )( root@centos7 ):/tmp/workspace
cat rule.txt | grep -i -f rule.txt
centos
redhat
#2.从文件中读取规则,并显示匹配内容的那一行的行号 (注意合并短选项时f选项要放在最后)
#( 06/10/18@10:19上午 )( root@centos7 ):/tmp/workspace
cat rule.txt | grep -inf rule.txt
1:centos
2:redhat
我来试一试
#1. 显示/proc/meminfo文件中以大写或小写S开头的行;用两种方式;
#( 06/02/18@10:20上午 )( root@centos7 ):~
cat /proc/meminfo | grep "^[Ss]"
SwapCached: 0 kB
SwapTotal: 0 kB
SwapFree: 0 kB
Shmem: 98612 kB
Slab: 116884 kB
SReclaimable: 105708 kB
SUnreclaim: 11176 kB
#( 06/02/18@10:20上午 )( root@centos7 ):~
cat /proc/meminfo| grep -i "^s"
SwapCached: 0 kB
SwapTotal: 0 kB
SwapFree: 0 kB
Shmem: 98612 kB
Slab: 116884 kB
SReclaimable: 105708 kB
SUnreclaim: 11176 kB
#2. 显示/etc/passwd文件中其默认shell为非/sbin/nologin的用户;
#( 06/02/18@10:21上午 )( root@centos7 ):~
cat /etc/passwd | grep -v "/sbin/nologin$"
root:x:0:0:root:/root:/bin/zsh
sync:x:5:0:sync:/sbin:/bin/sync
shutdown:x:6:0:shutdown:/sbin:/sbin/shutdown
halt:x:7:0:halt:/sbin:/sbin/halt
admin:x:1000:1000::/home/admin:/bin/zsh
hadoop:x:2000:2000:hadoop:/home/hadoop:/bin/bash
#3. 显示/etc/passwd文件中其默认shell为/bin/bash的用户;
#( 06/02/18@10:34上午 )( root@centos7 ):~
cat /etc/passwd | grep "/bin/bash$"
hadoop:x:2000:2000:hadoop:/home/hadoop:/bin/bash
#4. 找出/etc/passwd文件中的一位数或两位数;
#( 06/02/18@10:39上午 )( root@centos7 ):~
cat /etc/passwd | grep -E "\<[0-9][0-9]?\>"
root:x:0:0:root:/root:/bin/zsh
bin:x:1:1:bin:/bin:/sbin/nologin
daemon:x:2:2:daemon:/sbin:/sbin/nologin
adm:x:3:4:adm:/var/adm:/sbin/nologin
lp:x:4:7:lp:/var/spool/lpd:/sbin/nologin
sync:x:5:0:sync:/sbin:/bin/sync
shutdown:x:6:0:shutdown:/sbin:/sbin/shutdown
halt:x:7:0:halt:/sbin:/sbin/halt
mail:x:8:12:mail:/var/spool/mail:/sbin/nologin
#5. 显示/boot/grub/grub.conf中以至少一个空白字符开头的行;
#( 06/02/18@10:44上午 )( root@centos7 ):~
cat /boot/grub2/grub.cfg | grep -E "^[[:space:]]+"
load_env
set default="${next_entry}"
set next_entry=
save_env next_entry
set boot_once=true
set default="${saved_entry}"
#6. 显示/etc/fstab文件中以#开头,后面跟至少一个空白字符,而后又有至少一个非空白字符的行;
#( 06/02/18@10:58上午 )( root@centos7 ):~
cat /etc/fstab | grep -E "^#[[:space:]]+"
# /etc/fstab
# Created by anaconda on Fri Aug 18 03:51:14 2017
# Accessible filesystems, by reference, are maintained under '/dev/disk'
# See man pages fstab(5), findfs(8), mount(8) and/or blkid(8) for more info
#7. 打出netstat -tan命令执行结果中以‘LISTEN’,后或跟空白字符结尾的行;
#( 06/02/18@10:59上午 )( root@centos7 ):~
netstat -tan | grep -E "\<LISTEN[[:space:]]*$"
tcp 0 0 0.0.0.0:22 0.0.0.0:* LISTEN
tcp 0 0 127.0.0.1:32000 0.0.0.0:* LISTEN
#8. 添加用户bash, testbash, basher, nologin (此一个用户的shell为/sbin/nologin),而后找出当前系统上其用户名和默认shell相同的用户的信息;
#( 06/02/18@ 1:04下午 )( root@centos7 ):~
vim mysh/add_4_user.sh
#( 06/02/18@ 1:05下午 )( root@centos7 ):~
cat mysh/add_4_user.sh
useradd bash
useradd testbash
useradd basher
useradd -s /sbin/nologin nologin
#( 06/02/18@ 1:05下午 )( root@centos7 ):~
tail -4 /etc/passwd
bash:x:2001:2001::/home/bash:/bin/bash
testbash:x:2002:2002::/home/testbash:/bin/bash
basher:x:2003:2003::/home/basher:/bin/bash
nologin:x:2004:2004::/home/nologin:/sbin/nologin
#( 06/02/18@ 1:06下午 )( root@centos7 ):~
tail -4 /etc/passwd | grep "\(\<[a-z]\+\>\).*\1$"
bash:x:2001:2001::/home/bash:/bin/bash
nologin:x:2004:2004::/home/nologin:/sbin/nologin
#( 06/02/18@ 1:06下午 )( root@centos7 ):~
tail -4 /etc/passwd | grep -E "(\<[a-z]+\>).*\1$"
bash:x:2001:2001::/home/bash:/bin/bash
nologin:x:2004:2004::/home/nologin:/sbin/nologin
写在最后
grep结合正则表达式可以过滤出你想要内容,在脚本中也可以通过grep查找关键词,利用其命令状态返回值做判断条件,来确定某个内容是否存在哟。grep这个文本过滤工具,你get到了吗?\^_^