Linux grep 实战用法

时间:2022-9-2     作者:smarteng     分类: Linux命令


接着之前的 awk 实战用法,我们继续 Linux 常见命令系列,回顾一下 grep 的常见用法。想了解详细规则的同学可以参照 官方文档。这里我们重点放在快速入门,以及日常会用到的一些用法。

grep

grep 的全称是 global regular expression print,在 Linux 诸多命令行工具中可以说是最强大,最经常使用的。我们可以用 grep 来找到需要的文本信息。

其实和 awk 类似,本质也是给出一个 pattern,给出指定的查找范围(通常是一个文件),grep 就能来检索。当找到了匹配项之后,grep 会打印所有该文件中命中指定 pattern 的行。

尤其是当我们要在诸多 log 文件中找指定信息(比如 userID,orderID 等),用 grep 是非常简单方便的。

基本用法

grep 命令的基本格式如下,option 看需求,重点还是给出我们需要的 pattern,以及对应的文件

$ grep [options] PATTERN [FILE...]

Options Description
-c : This prints only a count of the lines that match a pattern
-h : Display the matched lines, but do not display the filenames.
-i : Ignores, case for matching
-l : Displays list of a filenames only.
-n : Display the matched lines and their line numbers.
-v : This prints out all the lines that do not matches the pattern
-e exp : Specifies expression with this option. Can use multiple times.
-f file : Takes patterns from file, one per line.
-E : Treats pattern as an extended regular expression (ERE)
-w : Match whole word
-o : Print only the matched parts of a matching line,
 with each such part on a separate output line.

-A n : Prints searched line and nlines after the result.
-B n : Prints searched line and n line before the result.
-C n : Prints searched line and n lines after before the result.
复制代码

这些 flag 大家混个眼熟就 ok,有一些我们会在后面介绍。下面先看看最常见的匹配:

还是用我们上一节在 awk 里的示例 employee.txt

ajay manager account 45000
sunil clerk account 25000
varun manager sales 50000
amit manager account 47000

tarun peon sales 15000
deepak clerk sales 23000
sunil peon sales 13000
satvik director purchase 80000
复制代码

如果我们希望查找 ajay 所在的行,可以用 grep ajay employee.txt ,就会得到:

ajay manager account 45000
复制代码

如果我们要找所有类型为 sales 的记录,运行 grep sales employee.txt ,就能看到:

varun manager sales 50000
tarun peon sales 15000
deepak clerk sales 23000
sunil peon sales 13000
复制代码

搜索文件名

在某个目录下,寻找匹配某个名称的文件,可以结合 lsgrep 的能力来做。

$ ls -l | grep employee

-rw-r--r--   1 bytedance  staff       209  8 28 23:47 employee.txt
复制代码

在多个文件中寻找字符串

基本格式为

grep “string” filename1 filename2
复制代码

为此我们将 employee.txt 拷贝一份,叫做 empbackup.txt,看看查找 "sale" 字符串的结果

$ grep sale employee.txt empbackup.txt

employee.txt:varun manager sales 50000
employee.txt:tarun peon sales 15000
employee.txt:deepak clerk sales 23000
employee.txt:sunil peon sales 13000
empbackup.txt:varun manager sales 50000
empbackup.txt:tarun peon sales 15000
empbackup.txt:deepak clerk sales 23000
empbackup.txt:sunil peon sales 13000
复制代码

通配符

其实多个文件的场景,如果前后缀一样,我们可以直接用 * 来代替。将上面的命令替换成:

$ grep sale emp*

empbackup.txt:varun manager sales 50000
empbackup.txt:tarun peon sales 15000
empbackup.txt:deepak clerk sales 23000
empbackup.txt:sunil peon sales 13000
employee.txt:varun manager sales 50000
employee.txt:tarun peon sales 15000
employee.txt:deepak clerk sales 23000
employee.txt:sunil peon sales 13000
复制代码

你会发现结果是一样的。后缀相同也是类似的写法。

忽略大小写

grep 支持忽略大小写的 flag 有三种写法:

  • -i

  • -y

  • --ignore-case

通常情况下我们会使用 -i 比较多。

我们把 employee.txt 中的 tarun 改成 Tarun 看一下:

$ grep tarun employee.txt
复制代码

此时没有数据返回。

$ grep -i tarun employee.txt

Tarun peon sales 15000
复制代码

数据返回,符合预期。

正则表达式

毕竟是 regular expression print,怎么能不支持正则表达式呢?这不就来了。

额外说一句,正则也是很多程序员的痛点,推荐一个在线网站,大家有时候不确定某段文本和正则是否匹配时,可以到 RegExr 试一下

undefined

举个例子,假设我们想根据开始单词,以及结束单词匹配,用正则来表达是这样: begin.*end

undefined

那么对应到 grep 的写法也非常简单,pattern 的位置直接写正则,加上引号,就 ok 了。

我们新建一个文本文件叫做 regtest.txt,填充以下内容:

RegExr was created by gskinner.com, and is proudly hosted by Media Temple.

Edit the Expression & Text to see matches. Roll over matches or the expression for details. PCRE & JavaScript flavors of RegEx are supported. Validate your expression with Tests mode.

The side bar includes a Cheatsheet, full Reference, and Help. You can also Save & Share with the Community, and view patterns you create or favorite in My Patterns.

Explore results with the Tools below. Replace & List output custom results. Details lists capture groups. Explain describes your expression in plain English.this made data
复制代码

执行 grep "this.*data" regtest.txt ,就能得到:

Explore results with the Tools below. Replace & List output custom results. Details lists capture groups. Explain describes your expression in plain English.this made data
复制代码

正好是最后一句。

由此又拓展出一个常见的场景,有时候我们想搜以 XXX 开头的行,这时候还是用正则的能力就能实现。^ 表达的就是开头的意思。所以我们的命令写出来是这样

$ grep "^unix" geekfile.txt
复制代码

同理,有了开头就有结尾,我们可以用 $ 的能力来匹配以 XXX 结尾的行

$ grep "os$" geekfile.txt
复制代码

上色

还是上面的正则的例子,坦率讲文本比较长的时候不好看出来,这个时候我们就可以用 --color 这个flag 来显示到底这一行的哪个部分 match 了我们提供的 pattern。

执行 grep "this.*data" regtest.txt --color 命令

最后匹配上的部分变成了红色,类似这样

undefined

打印匹配次数

有时候我们不需要真的看到那些匹配的行,而是只需要知道匹配了几次,这时候可以用 -c 这个 flag 来实现。

$ grep –c “string” filename
复制代码

假设我们的示例文件内容如下

undefined

执行 grep -c 之后就能输出出现次数:

undefined

排除搜索

前面都是我们给出一个 pattern,找能匹配上这个 pattern 的行。但有些时候我们是希望逆着来,找到不匹配这个pattern的行,grep 对此也提供了支持,也就是 -v。

还是用上一节的 testfile3,如果这次我们想找不包含 "account" 字符串的部分,就可以这样:

$ grep –v “account” testfile3
复制代码

得到结果是其他两行

undefined

全单词匹配

需要注意一点,虽然上面我们也有过直接匹配字符串的场景,但那本质返回的是包含了 pattern 字符串为子串的所有行。有些时候我们希望必须是独立的词才行。

比如搜索 a,有可能把 apple, banana, pear, a 这四个单词所在行都搜到,但实际上真正匹配全词的只有最后一个。

这种场景可以用 -w 来解决。

$ grep -w "unix" geekfile.txt

unix is great os. unix is opensource. unix is free os.
uNix is easy to learn.unix is a multiuser os.Learn unix .unix is a powerful.
复制代码

展示行号

这次用 -n 来实现,我们还是基于 employee.txt 搜索 sale。

$ grep -n sale employee.txt

3:varun manager sales 50000
6:Tarun peon sales 15000
7:deepak clerk sales 23000
8:sunil peon sales 13000
复制代码

最前面的 3,6,7,8 就是行号

递归整个目录

undefined
这个坦率的讲是笔者用的最多的功能,很多时候要找的不是一个文件,而是一个日志文件目录,这时候可以用 -R 的能力

$ grep -R [Search] [directory] 
复制代码

比如我们在 /home/geeks 目录下搜索 geeks,可以这样

$ grep -iR geeks /home/geeks
复制代码

得到的响应如下

./geeks2.txt:Well Hello Geeks
./geeks1.txt:I am a big time geek
复制代码

-i 是忽略大小写,-R 是递归检查目录下所有文件

小结

grep 其实和 awk 类似,这类经典工具支持的能力非常强大,建议大家对常用命令记熟练,然后保存好官方使用手册地址:www.gnu.org/software/gr…

在出现问题的时候能最快时间找到解法就 ok,倒是不必要每一条都非常熟练,毕竟工具越用越熟,不用可以去背。

参考资料

标签: grep