虽然grep命令不是直接搜索文件的工具(其用于打印匹配来自一个或多个文件的一种模式的行),你可以使用它定位位置。假如你知道在你正在查找的文件中一个短语或者你正在查找一个包含特定字符串的文件,grep会帮你列出包含一个特定短语的所有文件。

例如,如果你载在查询一个README.md文件,其包含了一个短语"An assortment",你怀疑这个名称的文件应该在你家目录中某个地方,你可以按如下定位它:

[blctrl@areadetector ~]$ grep -Ri ~ -e "An assortment"
或
[blctrl@areadetector ~]$ grep -Ri ~ -e "An assortment" | cut -d: -f1

此处grep标记:

  • -R:表示递归搜索指定的目录
  • -i:表示不区分大小写
  • -e:指定短语被用作一个用于搜索的模式
  • -d:指定分隔符
  • -f:指定要打印的字段

grep是一个在每种Linux发行版上都安装的强大文件模式搜索器。以下使用示例是你熟悉grep

基本使用

1、搜索和查找文件

有两个不同版本的Python在用,你不知道你RockyLinux上安装哪一个版本或者是否安装了任何模块。只要运行这个命令:

[blctrl@areadetector diffraction]$ rpm -qa | grep -i python
python3-hawkey-0.63.0-8.el8.x86_64
python38-setuptools-wheel-41.6.0-5.module+el8.5.0+672+ab6eb015.noarch
python3-pyparsing-2.1.10-7.el8.noarch
python38-jinja2-2.10.3-5.module+el8.5.0+672+ab6eb015.noarch
python3-cairo-1.16.3-6.el8.x86_64
python3-libcomps-0.1.18-1.el8.x86_64
python36-devel-3.6.8-38.module+el8.5.0+671+195e4563.x86_64
...

首先,我们运行rpm -qa,它列出在你系统上安装的*.rpm包。接着,我们把那些输出用管道输入到grep -i python命令,它只是表示"到grep和过滤掉并且返回在其中带有'python'的每样东西"。由于grep是区分大小写的,所以-i选项在那里忽略大小写。使用-i选项是一种养成的好习惯,除非你尝试确定一个更特定的搜索。

2、搜索和过滤文件

grep可以用于在单个文件或多个文件内搜索和过滤。-v选项告诉grep反向其输出,意味着不是打印输出行,而是做相反事情,打印不匹配表达式的所有行,这这里,没有#注释的行:

[blctrl@areadetector diffraction]$ cat /etc/fstab

#
# /etc/fstab
# Created by anaconda on Fri Jan  1 00:32:29 2016
#
# 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.
#
# After editing this file, run 'systemctl daemon-reload' to update systemd
# units generated from this file.
#
/dev/mapper/rl-root     /                       xfs     defaults        0 0
UUID=2a91513c-5b4f-43fa-8703-342700a4d86a /boot                   xfs     defaults        0 0
UUID=9170-5EA4          /boot/efi               vfat    umask=0077,shortname=winnt 0 2
/dev/mapper/rl-home     /home                   xfs     defaults        0 0
/dev/mapper/rl-swap     none                    swap    defaults        0 0
/dev/sda4  /home/blctrl                    xfs     defaults        0 0

[blctrl@areadetector diffraction]$ grep -v "#"  /etc/fstab

/dev/mapper/rl-root     /                       xfs     defaults        0 0
UUID=2a91513c-5b4f-43fa-8703-342700a4d86a /boot                   xfs     defaults        0 0
UUID=9170-5EA4          /boot/efi               vfat    umask=0077,shortname=winnt 0 2
/dev/mapper/rl-home     /home                   xfs     defaults        0 0
/dev/mapper/rl-swap     none                    swap    defaults        0 0
/dev/sda4  /home/blctrl                    xfs     defaults        0 0

3、只查找所有.txt文件

grep对于从stdout过滤非常有用。你想从各种扩展名的文件中找出所有名称中含ui两个字母但不含g的所有txt文件。使用find命令和两个grep管道:

[root@rockygu test]# find ./ -name "*.txt" | grep -i Ui | grep -vi G
./suid.txt

4、显示在搜索字符串前或后行数

另一对选项是-A和-B开关,它们显示匹配的行以及在之前或者在之后出现的行数。用-A=after和-B=before记住这两个选项是最简单的。

[root@rockygu test]# ifconfig | grep -A 4 eth0   # eth0以及其下4行
eth0: flags=4163<UP,BROADCAST,RUNNING,MULTICAST>  mtu 1500
        inet 172.28.133.248  netmask 255.255.240.0  broadcast 172.28.143.255
        inet6 fe80::216:3eff:fe20:888e  prefixlen 64  scopeid 0x20<link>
        ether 00:16:3e:20:88:8e  txqueuelen 1000  (Ethernet)
        RX packets 4108085  bytes 4247267173 (3.9 GiB)

[root@rockygu test]# ifconfig | grep -B 2 inet6   # inet6以及其上2行
eth0: flags=4163<UP,BROADCAST,RUNNING,MULTICAST>  mtu 1500
        inet 172.28.133.248  netmask 255.255.240.0  broadcast 172.28.143.255
        inet6 fe80::216:3eff:fe20:888e  prefixlen 64  scopeid 0x20<link>
--
lo: flags=73<UP,LOOPBACK,RUNNING>  mtu 65536
        inet 127.0.0.1  netmask 255.0.0.0
        inet6 ::1  prefixlen 128  scopeid 0x10<host>

5、打印在匹配两边的行数

grep的-C选项类似,但它打印匹配行以及上下各指定行数的行

[root@rockygu test]# ifconfig | grep -C 1 "inet\>"   # inet以及上下各1行
eth0: flags=4163<UP,BROADCAST,RUNNING,MULTICAST>  mtu 1500
        inet 172.28.133.248  netmask 255.255.240.0  broadcast 172.28.143.255
        inet6 fe80::216:3eff:fe20:888e  prefixlen 64  scopeid 0x20<link>
--
lo: flags=73<UP,LOOPBACK,RUNNING>  mtu 65536
        inet 127.0.0.1  netmask 255.0.0.0
        inet6 ::1  prefixlen 128  scopeid 0x10<host>

6、计算匹配次数

类似于管道传输一个grep字符串到单词计数(wc程序),grep的内建选项可以为你执行相同功能:

[root@rockygu test]# ifconfig | grep -c inet6
2

7、通过指定字符串搜索文件

当在编译错误过程中调式文件时,grep的-n选项非常有用。它显示文件中指定搜索字符串的行号。

[root@rockygu test]# grep -n "UUID" /etc/fstab
12:UUID=7347bc43-229b-4f3b-8759-2c54a6c55527 /                       xfs     defaults        0 0

8、在所有目录中递归搜索一个字符串

如果你想要在当前目录及其所有子目录中搜索一个字符串,你可以指定-r选项递归地搜索:

[root@rockygu test]# grep -ri "rock" *
fold/infold.txt:Rock
Rock.txt:Rock
Rock.txt:Rocky
Rocky/3.txt:rock
rocky.c:rocky
rocky.c:Rocky
rocky.c:Rock
rocky.c:rock

9、搜索完整模式

传递-w选项给grep搜索在字符串中完整模式。例如,使用:

[root@rockygu test]# ifconfig | grep -w "RUNNING"
eth0: flags=4163<UP,BROADCAST,RUNNING,MULTICAST>  mtu 1500
lo: flags=73<UP,LOOPBACK,RUNNING>  mtu 65536

将打印出在引号中包含这个模式的行。另一方面,如果你尝试:

[root@rockygu test]# ifconfig | grep -w "RUN"
[root@rockygu test]#

由于我们不搜索这个模式而是一整个单词,将没有东西返回。

10、在Gzipped文件中搜索一个字符串

值得一提的是grep的变体。首先是zgrep,其类似于zcat,用于gzipped文件。它接收与grep相同选项并且以相同方式使用。

[root@rockygu test]# zgrep -i rock Rock.txt.gz
Rock
Rocky

11、在文件中匹配正则表达式

egrep是另一个变体,其代表"扩展的全局正则表达式"。它识别补充的表达式源字符,诸如:@ + |和()。

egrep对于搜索源文件以及代码片段非常有用。通过指定-E选项从常规grep调用它。

[root@rockygu test]# ifconfig | grep -E "([0-9]{1,3}\.){3}[0-9]{1,3}"
        inet 172.28.133.248  netmask 255.255.240.0  broadcast 172.28.143.255
        inet 127.0.0.1  netmask 255.0.0.0

高级使用

1、搜索英文字母数字字符

如果你在一个文件中有数千行并且想要搜索只从A-Z,a-z以及0-9起始的行。

[blctrl@areadetector diffraction]$ grep "^[[:alnum:]]" /etc/fstab
UUID=2a91513c-5b4f-43fa-8703-342700a4d86a /boot                   xfs     defaults        0 0
UUID=9170-5EA4          /boot/efi               vfat    umask=0077,shortname=winnt 0 2

2、搜索英文字母

如果你在一个文件中有数千行并且想要搜索只从A-Z和a-z起始的行。

[blctrl@areadetector diffraction]$ grep "^[[:alpha:]]" /etc/fstab
UUID=2a91513c-5b4f-43fa-8703-342700a4d86a /boot                   xfs     defaults        0 0
UUID=9170-5EA4          /boot/efi               vfat    umask=0077,shortname=winnt 0 2

3、搜索空白字符

如果你想要搜索以[Tab和Space](即,空白字符)起始的行。

[root@rockygu test]# ifconfig | grep "^[[:blank:]]"
        inet 172.28.133.248  netmask 255.255.240.0  broadcast 172.28.143.255
        inet6 fe80::216:3eff:fe20:888e  prefixlen 64  scopeid 0x20<link>
        ether 00:16:3e:20:88:8e  txqueuelen 1000  (Ethernet)
        RX packets 4125086  bytes 4262134278 (3.9 GiB)
        RX errors 0  dropped 0  overruns 0  frame 0
        TX packets 2185587  bytes 1229047290 (1.1 GiB)
        TX errors 0  dropped 0 overruns 0  carrier 0  collisions 0
        inet 127.0.0.1  netmask 255.0.0.0
        inet6 ::1  prefixlen 128  scopeid 0x10<host>
        loop  txqueuelen 1000  (Local Loopback)
        RX packets 748  bytes 47245 (46.1 KiB)
        RX errors 0  dropped 0  overruns 0  frame 0
        TX packets 748  bytes 47245 (46.1 KiB)
        TX errors 0  dropped 0 overruns 0  carrier 0  collisions 0

4、搜索数字字符。

用于grep的数字选项对于搜索以[0-9]数字开始的行非常有用。

[root@rockygu test]# grep "^[[:digit:]]" Rock.txt
123 Rock
0 ABC

5、搜索小写字符

用于grep的另一个选项是搜索小写字母开头[a-z]的行。

[root@rockygu test]# grep "^[[:lower:]]" Rock.txt
rock 123
abc 456

6、搜索标点符号

用于grep的标点符号是搜索以[! " # $ % ' ( ) * + , - . / : ; < = > ? @ [ \  ] ^ _ ` { | } ~.] 即是:标点字符。

[root@rockygu test]# grep "^[[:punct:]]" Rock.txt
!1
"2
#3
$4
%5
&6
'7
(8
*9
+10
.11
:12
;13
<14
=15
?16
@17
[18
\19
^20
_21
{22
|23
~24

7、搜索图形字符

grep也用于搜索从被称作图形字符的字母数字以及标点字符开始的行。

[root@rockygu test]# grep "^[[:graph:]]" Rock.txt
Rock 123
Rocky 456
123 Rock
0 ABC
rock 123
abc 456
!1
"2
#3
$4
%5
&6
'7
(8
*9
+10
.11
:12
;13
<14
=15
?16
@17
[18
\19
^20
_21
{22
|23
~24

8、搜索可打印字符

类似于图形字符,grep对搜索从字母数字,标点字符和空白字符开头的行有用。

[root@rockygu test]# grep "^[[:print:]]" Rock.txt

9、搜索空白字符

grep也有搜索以[tab, newline, vertical tab, form feed, carriage return和space](即是:空白字符)开头的行。

[root@rockygu test]# grep "^[[:space:]]" Rock.txt

10、搜索大写字母

[root@rockygu test]#  grep "^[[:upper:]]" Rock.txt
Rock 123
Rocky 456

11、搜索十六进制数字

grep搜索从[0-9 A-F 和a-f]起始的行,即是:十六进制数字。

[root@rockygu test]#  grep "^[[:xdigit:]]" Rock.txt
123 Rock
0 ABC
abc 456
Fa
a1