grep
Linux系统中grep命令是一种强大的文本搜索工具,它能使用正则表达式搜索文本,并把匹 配的行打印出来。grep全称是Global Regular Expression Print,表示全局正则表达式版本,它的使用权限是所有用户。
Usage
$ grep
usage: grep [-abcDEFGHhIiJLlmnOoqRSsUVvwxZ] [-A num] [-B num] [-C[num]]
[-e pattern] [-f file] [--binary-files=value] [--color=when]
[--context[=num]] [--directories=action] [--label] [--line-buffered]
[--null] [pattern] [file ...]
主要参数:
-c
:只输出匹配行的计数。-I
:不区分大小写(只适用于单字符)。-h
:查询多文件时不显示文件名。-l
:查询多文件时,只输出包含了匹配字符传的文件的文件名。-n
:显示匹配行及行号。-s
:不显示不存在或无匹配文本的错误信息。-v
:显示不包含匹配文本的所有行。
查找文件
在多个文件中查询特定字符串
$ grep ‘test’ aa bb cc
输出在aa,bb,cc文件中匹配到 test
字符串的行。
在文件夹中查找存在特定字符串的文件
比如,我们在当前子目录下,查找哪些文件中存在字符串"aa":
$ grep aa ./*
grep: ./assets: Is a directory
./【刷题】LinkedList-Leetcode-138-Copy-List-with-Random-Pointer.md:![动画描述](assets/16a2de34a98aa550.gif)
./【刷题】LinkedList-Leetcode-160-Intersection-of-Two-Linked-Lists.md:aa
./【刷题】LinkedList-Leetcode-160-Intersection-of-Two-Linked-Lists.md:aa
默认情况下,grep
只搜索当前目录。如果此目录下有许多子目录,grep
会以如下形式列出:
$ grep: ./assets: Is a directory
这可能会使 ‘grep
的输出难于阅读。这里有两种解决的办法:
- 搜索子目录:
grep -r
- 或忽略子目录:
grep -d skip
查找所有以d字符开头作为文件名的文件,且文件中包含 test
字符串
$ grep ‘test’ d*
-l
- 只列出包含匹配字符串的文件的文件名
$ grep -l "assets/*.*" ./*
./2
-r
- 搜索子目录
$ grep -r 'string' /etc
默认情况下,grep
只搜索当前目录。如果此目录下有许多子目录,grep
会以如下形式列出:
$ grep: ./assets: Is a directory
-h
- 查询多文件时不显示文件名
$ grep -h "assets/*.*" ./*
test1 ![img](assets/160_statement.png) test2
--include="s3*"
- 只考虑特定文件名的文件
$ grep <keyword> --include=<file name pattern>
# 包含 abc 且文件名以 s3 开头的所有匹配内容
$ grep abc -rl --include="s3*" ./
.//s3_deploy.sh
-a
- 视为文本文件
-a
,--text
: Process a binary file as if it were text; this is equivalent to the –binary-files=text option.
$ grep -a <keyword> 1.bin
当出现下面这种错误的时候,就可以加上 -a
:
$ grep -a "ormstats" 1.log
Binary file 1.log matches
匹配定制
-i
- 不区分大小写地搜索
不区分大小写地搜索。默认情况区分大小写,
$ grep -i pattern files
-w
- 只匹配整个单词
只匹配整个单词(单词意味着这个字符串的两侧有分隔符),而不是字符串的一部分(如输入 magic
,匹配 magic
,而 magical
不能被匹配),
$ grep -w pattern files
-F
- 将输入模式视为一个普通字符串
$ cat aa.txt
/sw/
asdasd
sdsd
$ grep -F "/sw/" *.txt
/sw/
# or use --fixed-strings to search for an exact string (disables regular expressions):
$ grep --fixed-strings "exact_string" path/to/file
# escape character
$ grep -F "applicable/":true"
或匹配
输出匹配 pattern1 或 pattern2 的行:
$ grep pattern1 | pattern2 files
也可以,输出包含 ed
或者 at
字符的行的内容
$ cat test.txt | grep -E "ed|at"
与匹配
显示既匹配 pattern1 又匹配 pattern2 的行内容。
$ grep pattern1 files | grep pattern2
比如
$ grep proctm log/data.log | grep ormstats
输出 log/data.log
文件中既包含 proctm
又包含 ormstats
的行。
-v
- 非匹配(匹配不包含特定字符串的所有行)
$ grep -v pattern1 files
比如我想查看apaceh日志中,非图片的浏览记录。可以使用以下命令:
$ tail -f /usr/loca/apache/logs/access.log | grep -v '.jpg'
这条命令就可以针对apaceh的用户访问记录中,除了.jpg
图片之外的浏览日志,这样可以针对我们更好的分析日志了。
当然你可以再加 |grep -v '.png'
这样又可以排除 .png
格式的图片访问日志。
控制输出
-o
- 只输出匹配到的那个字符串部分
如果不包含 -o
(不包含 -o
为默认情况),则会把匹配到的那个部分所在的那一整行都输出到 terminal。
$ cat ./file
test1 ![img](assets/160_statement.png) file
test3
$ grep "assets/*.*" ./file
test1 ![img](assets/160_statement.png) file
$ grep -o "assets/*.*" ./file
assets/160_statement.png)
而如果包含 -o
之后,只输出被匹配到的那部分字符串。
-n
- 同时列出匹配字符串所在行的行号
$ grep -n "assets/*.*" ./file
1:test1 ![img](assets/160_statement.png) test2
这里列出了行号为 1。
-c
- 输出匹配上模式的行的数量
比如,查找指定进程个数
$ ps -ef | grep -c svn
-m 1
- 只输出匹配上的第一个行(第二个行和后面的行都不输出,即使匹配上了)
grep与正则表达式
pattern正则表达式主要参数:
\
: 忽略正则表达式中特殊字符的原有含义。^
:匹配正则表达式的开始行。$
: 匹配正则表达式的结束行。\<
:从匹配正则表达式的行开始。\>
:到匹配正则表达式的行结束。[<candidate_character>]
:指定单个字符集合,如[A]
表示只匹配字符A
。[<candidate_character>-<candidate_character>]
:指定字符字符集合范围,如[A-Z]
,即匹配A、B、C…或 Z 。.
:匹配任意的单个字符。*
:匹配任何长度从0到无穷的字符串。
Case 1 - 输出存在字符集合中任何一个字符的行的内容
输出包含任何小写字母的行
$ cat size.txt | grep '[a-b]'
b124230
b034325
a081016
a022021
a061048
b103303
a013386
b044525
Case 2 - 不是特定字符开头
# 输出行首既不是以4,也不是以8开头的所有行的内容
$ grep '^[^48]' data.doc
# 输出行首不是以 u 开头的所有行的内容
cat test.txt |grep ^[^u]
Case 3 - 输出以特定字符串结尾的行
$ cat test.txt | grep hat$
Misc
Use grep
in Shell Script
targets=($(grep -HRl "pattern" .))
- use of
(...)
for array creation in BASH. - use
grep -l
to get only file names ingrep
’s output
注意到,有一个问题是:
# 当前目录下,有三个文件
$ find .
.
./.DS_Store
./1.png
./1 2.png
$ my_files=(`find . | grep "png" | awk -F "\n" '{print $1}'`)
# or
$ my_files=($(find . | grep "png" | awk -F "\n" '{print $1}'))
$ echo $my_files
./1.png ./1 2.png
# get array's len
$ echo ${#my_files[@]}
3
即,如果文件的名称中包括空格时,获得的array会有问题。
grep
with find
Grep can be used with any other command you like. Let’s say I want to find any log files containing the word spice. I can use the find command and pipe the results to grep as follows:
$ find . -name "\*.log" | grep -i spice
Here’s an example of the results:
./spice-vdagent.log
Reference
- https://stackoverflow.com/questions/24890764/store-grep-output-in-an-array
- https://www.techrepublic.com/article/10-ways-to-use-grep-to-search-files-in-linux/