4

linux 三剑客 - 文本查找命令 grep

 3 months ago
source link: https://xujinzh.github.io/2024/01/27/linux-grep/
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.

linux 三剑客 - 文本查找命令 grep

发表于2024-01-27|更新于2024-01-29|technologylinux
字数总计:2.5k|阅读时长:9分钟|阅读量:8

linux 提供了强大的文本分析工具,如 grep, sed, awk,号称三剑客。本篇介绍文本查找命令 grep

grepglobal regular expression print)命令能够过滤出文本中符合要求(如正则表达式)的内容、行、文件等。默认在所有 linux 发行版中都预装该命令。

基本命令格式

grep [options|flags] pattern file1 file2 
# 查找系统上某个用户(如 root)的默认登录 shell
# 这里省略了 options 或 flags
# pattern 是 "root",pattern 可以用正在表达式,建议用引号包裹
# /etc/passwd 是文件名. grep 后面可以跟多个文件名
# | 管道符是把 grep 输出的一行内容按照 : 分割为多列,只打印最后一列
grep "root" /etc/passwd | awk -F ":" '{print $NF}'

options

options 有时也叫作 flags,是控制 grep 命令输出内容的参数。下面罗列一些常用的参数,更多请帮助文档:man grep

  • –color=always, –color=auto, –color=never: 是否以不同颜色显示查找到的文本内容
  • -a, –text:不要忽略二进制数据。用于从二进制文件中查找内容。如果查找二进制文件里的内容,请添加该参数:grep -a "合并" binary_files,查找二进制文件中是否包含有 “合并”
  • -A num, –after-context=num:对于查找到的某一行同时打印该行后 num 行内容,常用于日志分析,如打印报错内容的后面内容:grep -A 3 "error" run.log,查找 run.log 中包含有 error 行及其后 3 行
  • -B num, –before-context=num:与 -A num 相反,打印某一行的前 num 行:grep -B 3 "error" run.log,查找 run.log 中包含有 error 行及其前 3 行
  • -C num, –context=num:同时包含 -A num 和 -B num,表示打印找到的某一行的前后各 num 行:grep -C 3 "error" run.log,查找 run.log 中包含有 error 行及其前后 3 行
  • -c:只打印匹配的行数,不打印查找到的文本内容
  • -e pattern, –regexp=pattern:指定字符串作为查找文件内容的范本样式,这里字符串可以是正则表达式(下面介绍),可以指定多个 -e,用于查找多个内容:grep -e "root" -e "bash$" /etc/passwd,查找 root,以及以 bash 结尾的行
  • -E pattern, –extended-regexp=pattern:扩展正则表达式,即 egrep,指定可以使用扩展的正则表达式(下面介绍),示例:grep -E "ro+t" /etc/passwd,查找 root, rooot, …
  • -i, –ignore-case:忽略字符大小写,如同时查找 h 和 H:grep -i "h" /etc/passwd,查找 /etc/passwd 中包含有 h,H 的行
  • -l, –file-with-matches: 列出文件内容符合指定的 pattern 的文件名称: grep -l "root" /etc/*,查找 /etc 目录下所有包含 root 文本内容的文件名
  • -L, –files-without-match: 列出文件内容不符合指定的 pattern 的文件名称: grep -L "root" /etc/*,列文件夹 /etc 下不包含文本内容 root 的所有文件名
  • -n, –line-number: 打印找到的那一行内容前增加上行号:grep -n "root" /etc/passwd
  • -q, –quiet或–silent:不显示任何信息
  • -R/-r, –recursive: 递归搜索文件夹里面的文件,与 -d recurse 参数含义相同。
    # 递归搜索 /etc 目录下所有文件包含 root 内容的行
    grep -r "root" /etc

    # 递归搜索 ./codes 目录下所有以 py,sh,php,html,txt,md 结尾的文件里含有 sam 的行
    grep -r --include=*.{py,sh,php,html,txt,md} "sam" ./codes

    # 递归搜索 ./codes 目录下所有包含 sam 的文件行,但不包含以 .json 结尾的文件
    grep -r --exclude=.json "sam" ./codes

    # 递归搜索 ./codes 目录下所有文件包含 sam 的文件行,但是排除文件 filelist 中列出的所有文件
    grep -r --exclude-from=filelist "sam" ./codes

    # 递归搜索 ./codes 目录下所有文件包含 sam 的文件行,但是排除文件夹 py
    # py 可以是 codes 下的文件夹,也可以是其下子文件夹里的文件夹,但只需要指定文件夹名即可,不需要写相对或绝对路径
    grep -r --exclude-dir=py "sam" ./codes
  • -s, –no-messages:不显示错误信息
  • -v, –revert-match:反转查找,即对于匹配到的 pattern 不显示,如:ps ef | grep python | grep -v grep,查找 python 进程,但是不显示 grep 查找自己的进程
  • -V, –version:显示版本信息
  • -o:只输出文件中匹配到的部分,不打印行自打印查找到的文本内容本身
  • -m , –max-count=:找到 num 行结果后停止查找,用来限制匹配行数
# 查找文件中有多少个 sam 文本内容
grep -i "sam" image_sam_annotate.py -o -c

pattern

pattern 可以是文本内容,也可以是正则表达式,或扩展正则表达式。

正则表达式

使用正则表达式:

# 可以指定多个 -e
grep -e "xxx" filepath
符号 含义
^ 锚定行的开始,如 “^import” 匹配所有以 import 开头的行
$ 锚定行的介绍,如 “p$” 匹配所有以 p 结尾的行
^$ 匹配空白行
. 匹配一个非换行符的字符,如 “impo.t” 可以匹配 import,impoot, …
* 匹配零个或多个前一个字符,如 “1*” 匹配 1 后零个或多个 1
.* . 和 * 一起使用可以匹配任意字符
[] 匹配一个指定范围内的字符,如 “[a-z]” 匹配字符 a 到 z 的所有单个小写字符,”[0-9a-zA-Z]” 匹配所有单个数字或字符
[^] 与 [] 相反,匹配一个不在指定范围外的字符,如 “[^0-57-9]” 只匹配数字 6
\< 锚定单词的开始,如 “<np” 或 “\bnp”,匹配某行中独立的以np开头的单词,不一定在行首
\> 锚定单词的结束,如 “np>“ 或 “np\b”,匹配某行中独立的以 np 结尾的单词,不一定在行尾
\w 匹配一个英文字符或数字,同[0-9a-zA-Z]
\W 与 \w 相反,匹配除了英文字符和数字外的单个字符
\b 单词锁定,”\bas\b” 或者 “<as>“ 只匹配单词 as

Linux 系统中默认在每行行尾添加上符号 $,可以通过命令 cat -A file 查看

# 表示匹配一个数字+b组成的字符对
grep -e "[0-9]b" file

# 如果 -e 想要使用下面的扩展正则,需要增加反斜线 \,如 \?, \{m,n\}, \(x\)s

扩展正则表达式

扩展正则表达式(ERE,Extended Regular Expression),在正则表达式的基础上增加上 {}()?+|

grep -E "xxx" file
符号 含义
+ 匹配前面的一个字符 1 次或多次
? 匹配其前面的字符 1 次或 0 次,使用 grep “a?b” file, 匹配 b, ab
x{m} 重复字符 x 正好 m 次
x{m,} 重复字符 x 至少 m 次
x{m,n} 重复字符 x 至少 m 次,至多 n 次,默认以贪婪匹配,匹配字符尽量多
(x) 标记匹配字符,x 内容被标记为 \1
| | 表示或,如 a|b 表示匹配 a 或者 b
# 表示 ab 整体作为匹配字符,且匹配至少一次
grep -E "(ab){1,}" file

# \1 引用第一个左括号, \2 引用第二个左括号
grep -E "(l..e).*\1r" file

# 匹配结果如下:
He love his lover.
She like her liker.

POSIX字符

为了在不同国家的字符编码中保持一至,POSIX(The Portable Operating System Interface)增加了特殊的字符类,如 [:alnum:] 是 [A-Za-z0-9] 的另一个写法。要把它们放到 [] 号内才能成为正则表达式,如 [A- Za-z0-9] 或 [[:alnum:]]。在 linux 下的 grep 除 fgrep 外,都支持 POSIX 的字符类。

  • [:alnum:] # 文字数字字符,表示所有字母和数字 [0-9a-zA-Z]
  • [:alpha:] # 文字字符,表示所有字母(包含大小写) [a-zA-Z]
  • [:digit:] # 数字字符,所有数字 [0-9]
  • [:graph:] # 非空字符(非空格、控制字符)
  • [:lower:] # 小写字符,所有小写字母 [a-z]
  • [:cntrl:] # 控制字符
  • [:print:] # 非空字符(包括空格)
  • [:punct:] # 标点符号,所有标点符号
  • [:space:] # 所有空白字符(新行,空格,制表符), 表示空格或tab键
  • [:upper:] # 大写字符,所有大写字母 [A-Z]
  • [:xdigit:] # 十六进制数字(0-9,a-f,A-F)
item description
0 A match was found
1 No match was found
>1 A syntax error was found or a file was inaccessible (even if matches were found)

与其他命令结合

# echo 
echo "hello, world!" | grep hello

# tail
tail -f x.log | grep 2024

# ps
ps -aux | grep python | grep -v grep
ps -ef | grep python | grep -v grep

# wc, 输出 行数(wc -l),单词数(wc -w),字节数(wc -m )
# 字符数(wc -c,注意结尾$也算一个字符)
echo "hello, world" | wc

# xargs
find ~ -name "*.py" -print | xargs grep "import"

# awk
ps aux | grep "python" | grep -v grep | awk '{print "kill -9" $2}' | sh
ps aux | grep "python" | grep -v grep | awk '{print $2}' | xargs kill -9
kill -9 `ps aux | grep "python" | grep -v grep | awk '{print $2}'`

# 其他杀进程根据程序名
pgrep "python" | xargs kill -s 9
kill -o `pgrep "python"`
# pgrep "python" 等价于上面的 ps aux | grep "python" | grep -v grep | awk '{print $2}'

pkill -9 "python" # 名字不需要全名
pkill -u admin # 删掉用户 admin 运行的所有进程

killall "python" # 名字需要全名

About Joyk


Aggregate valuable and interesting links.
Joyk means Joy of geeK