Linux文本处理三剑客之grep

简述grep 工具和正则表达式的使用

定义

正则表达式使用单个字符串来描述、匹配一系列匹配某个句法规则的字符串。在很多文本编辑器里,正则表达式通常被用来检索、替换那些匹配某个模式的文本。许多程序设计语言都支持利用正则表达式进行字符串操作

grep:Global search Regular Expression and Print out the line,全面搜索正则表达式并把行打印出来,是一种强大的文本搜索工具,它能使用正则表达式搜索文本,并把匹配的行打印出来。
GUN/linux下grep包括 grepegrepfgrep

  • egrep是grep的扩展,等同grep -E
  • fgrep就是fixed grep或fast grep,等同grep -F不使用任何正则表达式,直接进行字符串匹配

语法

grep [OPTION] PATTERN [FILE]…

-o:只显示被模式匹配到的内容
-i:ignore case,不区分字符大小写
-E:使用扩展的正则表达式
-w:匹配一个完整的单词
-v:没有匹配到的行
-n:打印出匹配字符串的在文件中的行号
-c:统计个数
--color:对匹配的字符串着色打印
-5:匹配字符及前后各5行
-A 5:匹配字符及后5行,同-C 5
-B 5:匹配字符及前5行

1
grep -oin 'root' /etc/passwd    # 显示行号,不区分大小写只显示匹配到的字符本身

正则用法

字符匹配

.:匹配任意单个字符
[]:匹配指定范围内的任意单个字符
[^]:匹配指定范围外的任意单个字符
[0-9]:匹配数组 0-9 的任意一个
[0-z]:匹配任一数字及小写字母
[0-Z]:匹配任一数字及大小写字母
[[:digit:]]:匹配任意单个数字
[[:lower:]]:匹配任意单个小写字母,等同[a-z]
[[:upper:]]:匹配任意单个大写字母,等同[A-Z]
[[:space:]]:匹配任意单个空白字符
[[:punct:]]:匹配任意单个标点符号
[[:alpha:]]:匹配任意单个英文字母
[[:alnum:]]:匹配任意单个字母或数字

1
grep  [^0-9[:lower:]]  /etc/passwd      # 匹配除数字和小写字母以外的字符

匹配次数

*:匹配前面的字符任意次
.*:匹配任意次 .,即匹配任意长度的任意字符
\? :匹配前面的字符 0 次或者 1 次
\+ : 匹配前面的字符 1 次或多次
\{m\}:匹配前面的字符 m 次
\{m,n\}:匹配前面的字符至少 m 次,至多 n 次
\{m,\}:匹配前面的字符至少 m 次
\{,n\}:匹配前面的字符至多 n 次

  • 使用egrep或grep -E时,可去掉前面的转义符\
1
grep "[0-9]\+.*[[:punct:]]\{3,\}" /etc/passwd    # 至少一个数字及3个以上标点符号

位置锚定

^:锚定行首
$:锚定行尾
\<\b:锚定词首
\>\b:锚定词尾

1
2
3
grep -n "^[[:space:]]\+$" mydata.txt                  # 找出空白行的行号
grep "^#[[:space:]]\{1,\}[^[:space:]]" /etc/inittab # 以#开头,且后面跟一个或多个空白字符,而后又跟了任意非空白字符的行
grep '^\([0-9]\).*\1$' /etc/inittab # 一个数字开头并以一个与开头数字相同的数字结尾的行

分组引用

可以使用括号\(***\)将一组字符括起来,表示这一组字符被当作一个整体,还可以使用 \1, \2… 对前面括号匹配所匹配的字符串进行引用

1
2
3
4
5
6
7
8
9
10
11
# 首个单词和最后一个单词一样的行
grep "^\(\<[[:alpha:]]\+\>\).*\1$" /etc/passwd

# 匹配包含mysql或apache或redis的行,`|`表示或
egrep "mysql|apache|redis" mydata.txt

# 匹配ipv4的地址
egrep "(\<([0-9]|[1-9][0-9]|1[0-9][0-9]|2[0-4][0-9]|25[0-5])\>\.){3}\<([0-9]|[1-9][0-9]|1[0-9][0-9]|2[0-4][0-9]|25[0-5])\>"

# 取出默认shell为bash,且其用户ID号最小的用户的用户名
grep 'bash$' /etc/passwd | sort -n -t: -k3 | head -1 | cut -d: -f1

零宽断言

仅列2个比较常用的

  • (?=exp):匹配exp前面的位置
  • (?<=exp):匹配exp后面的位置
1
2
3
4
5
echo 'Nice to meet you' | grep -oP '(.+(?=eet))'
echo 'Nice to meet you' | grep -oP '((?<=Nice).+)'

# 提取本机IP
ip a | grep -v '127.0.0.1'| grep -oP '(?<=inet )[\d\.]+'