> 技术文档 > Shell的正则表达式

Shell的正则表达式


1 正则表达式简介

1.1 什么是正则表达式

在编写处理字符串的程序或网页时,经常会有查找符合某些复杂规则的字符串的需要。

正则表达式就是用于描述这些规则的工具。换句话说,正则表达式就是记录文本规则的代码。

正则表达式又称正规表达式、常规表达式。在代码中常简写为 regex、regexp 或 RE。

正则表达式是使用单个字符串来描述、匹配一系列符合某个与语法规则的字符串,简单来说,是一种匹配字符串的方法,通过一些特殊符号,实现快速查找、删除、替换某个特定字符串。

1.2 正则表达式示例

0和非0打头的一串数字:^0$|^[1-9][0-9]*$

验证汉字:^[\\u4e00-\\u9fa5]{0,}$

1.3 正则表达式作用

  • 测试字符串内的模式

测试输入字符串,以查看字符串内是否出现电话号码模式或信用卡号码模式。这称为数据验证。

  • 替换文本

使用正则表达式来识别文档中的特定文本,完全删除该文本或者用其他文本替换它。

  • 基于模式匹配从字符串中提取子字符串

查找文档内或输入域内特定的文本。

1.4 应用领域

正则表达式已经在很多软件中得到广泛的应用,包括 *nix(Linux, Unix等)、HP 等操作系统,C#、Java 等开发环境,以及很多的应用软件中,都可以看到正则表达式的影子。

C# 正则表达式、Java 正则表达式、JavaScript 正则表达式、Python 正则表达式等

对于系统管理员来说,正则表达式则是必备技能之一。通过正则表达式快速提取“有问题”的信息。如此一来,可以将运维工作变得更加简单、方便。

1.5 正则表达式语法综述

正则表达式是由普通字符(例如字符 a 到 z)以及特殊字符(称为\"元字符\")组成的文字模式。

元字符不表示字符字面意义,而表示控制或通配的功能,类似于增强版的通配符功能。
但与通配符不同,通配符功能是用来处理文件名,而正则表达式是处理文本内容中字符。

模式描述在搜索文本时要匹配的一个或多个字符串。

正则表达式作为一个模板,将某个字符模式与所搜索的字符串进行匹配。

在 Shell 中,正则表达式使用的是 POSIX 扩展正则表达式语法(extended regular expression syntax)。
常见的元字符和字符类如下:

字符 说明 . 匹配一个任意字符(\\n除外) ^ 匹配行首 $ 匹配行尾 * 匹配前一个字符出现0次或多次 + 匹配前一个字符出现1次或多次 ? 匹配前一个字符出现0次或1次 | 表示或操作 [charset] 匹配字符集中的任意一个字符 [^charset] 匹配非字符集中的任意一个字符 [a-z] 匹配a~z范围内的任意一个小写字母 [A-Z] 匹配A~Z范围内的任意一个大写字母 [0-9] 匹配0-9范围内的任意一个数字 \\s 匹配任意空白字符,包括空格、制表符、换行符等 \\S 匹配任意非空白字符

2 正则表达式基础

2.1 基础正则表达式常见元字符

  • \\:转义字符(

用于取消特殊符号的含义,如:\\n、\\$

  • ^:匹配字符串开始的位置

  • $:匹配字符串结束的位置

  • .:匹配除\\n之外的任意一个字符

  • *:匹配前面表达式重复0次或多次

  • [list]:匹配list列表中的一个字符

  • [^list]:匹配任意非list列表中的一个字符

  • \\{n\\}:匹配前面的表达式n次

  • \\{n,\\}:匹配前面的表达式至少n次

  • \\{,n\\}:匹配前面的表达式最多n次

  • \\{n,m\\}:匹配前面的表达式n到m次

  • \\w:匹配包括下划线的任何单词字符,等价于[a-zA-Z0-9_]

  • \\W:匹配任何非单词字符,等价于[^a-zA-Z0-9_]

  • \\s:空白符,如:空格符、换行符、回车符等

  • \\S:非空白符

  • 支持的工具:

grep、egrep、sed、awk

2.2 查找特定字符和组合

从 test.txt 文件中查找出特定字符“the”所在位置

-n表示显示行号
-i表示不区分大小写

命令执行后,符合匹配标准的字符,字体颜色会变为红色

grep -n \'the\' test.txtgrep -i \'the\' test.txt

2.2.1 通配符[]

[charset]为候选字符集,即匹配其中的一个即可

grep -n \'sh[io]rt\' test.txt

[io] 表示匹配 i 或者 o

# 查找包含数字的行grep -n \'[0-9]\' test.txt

2.2.2 反向选择[^]

^在[]中时,表示取反,如[^a]表示不是a

# 查找oo前面不存在数字字符串grep -n \'[^0-9]oo\' test.txt# oo前面不存在小写字母grep -n \'[^a-z]oo\' test.txt# oo前面不存在大写字母grep -n \'[^A-Z]oo\' test.txt

2.2.3 行首字符^

# 以the字符串为行首的行grep -n \'^the\' test.txt# 小写字母开头的行grep -n \'^[a-z]\' test.txt# 大写字母开头的行grep -n \'^[A-Z]\' test.txt# 不以字母开头的行grep -n \'^[^a-zA-Z]\' test.txt

2.2.4 行尾字符$

# 以s结尾的行grep -n \'s$\' test.txt# 空白行grep -n \'^$\' test.txt# 不是查询以ti开头,以ti结尾的行,而是只有ti的行grep –n ‘^ti$’ test.txt

2.2.5 边界字符\\b

查询以指定字符为边界的单词

# 以s开头的单词grep –n ‘\\bs’ test.txt# 以s结尾的单词grep –n ‘s\\b’ test.txt
  • \\B 非边界

2.2.6 任意字符.

在正则表达式中小数点(.)也是一个元字符,匹配除\\n之外的任意的一个字符。

# 以 w 开头 d 结尾,共有四个字符的字符串grep -n \'w..d\' test.txt

2.2.7 重复字符*

匹配前面子表达式0次或者多次

# 包含至少两个以上 o 的字符串grep -n \'ooo*\' test.txt# 以 w 开头 d 结尾,中间包含至少一个 o 的字符串grep -n \'woo*d\' test.txt# 以 w 开头 d 结尾,中间的字符可有可无的字符串grep -n \'w.*d\' test.txt

2.2.8 连续字符范围{}

  • \\{n\\}:匹配前面的表达式n次
# 两个 o 的字符grep -n \'o\\{2\\}\' test.txt
  • \\{n,\\}:匹配前面的表达式至少n次
# 以 w 开头以 d 结尾,中间包含至少2个 o 的字符串grep -n \'wo\\{2,\\}d\' test.txt
  • \\{,n\\}:匹配前面的表达式最多n次
# 以 w 开头以 d 结尾,中间包含最多5个 o 的字符串grep -n \'wo\\{,5\\}d\' test.txt
  • \\{n,m\\}:匹配前面的表达式n到m次
# 以 w 开头以 d 结尾,中间包含 2~5 个 o 的字符串grep -n \'wo\\{2,5\\}d\' test.txt

3 正则表达式进阶

3.1 正则表达式元字符扩展

  • +:匹配前面表达式1次以上
  • ?:匹配前面表达式0次或1次
  • ():将括号中的字符串看作一个整体
  • |:以或的方式匹配字符串
  • 支持的工具:

egrep、awk、grep -E、sed -r

3.2 egrep命令

grep 命令仅支持基础正则表达式,如果使用扩展正则表达式,需要使用 egrep或 awk 命令。

egrep 命令与 grep 命令的用法基本相似。egrep 命令是一个搜索文件获得模式,使用该命令可以搜索文件中的任意字符串和符号,也可以搜索一个或多个文件的字符串,一个提示符可以是单个字符、一个字符串、一个字或一个句子。

# 大小写不敏感搜索egrep -i \"test\" test.txt# 查找以大写字母开头的行egrep \"^[A-Z]\" test.txt# 查找包含三个或更多连续 o 的行egrep \"o{3,}\" test.txt

3.2.1 |示例

# 包含 test 或 than的行egrep -n \'test|than\' test.txt

3.2.2 ()示例

# 包含至少两个连续相同字符的行egrep -n \'(.)\\1\' test.txt

(.):这是一个捕获组(capturing group)。它捕获任意单个字符,并将其存储在一个临时缓冲区中。括号 ()用于定义捕获组。

\\1: 这是对第一个捕获组的反向引用(backreference)。它表示与第一个捕获组中捕获的
字符相同的内容。

(.)\\1:捕获任意一个字符,然后查找紧跟在这个字符后面的相同字符。

3.2.3 +示例

# 包含两个或更多连续 l 的行egrep -n \'ll+\' test.txt