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:
./【刷题】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  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  file
test3
$ grep "assets/*.*" ./file
test1  file
$ grep -o "assets/*.*" ./file
assets/160_statement.png)
而如果包含 -o 之后,只输出被匹配到的那部分字符串。
-n - 同时列出匹配字符串所在行的行号
$ grep -n "assets/*.*" ./file
1:test1  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 -lto 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/