正则表达式常见用法(持续更新)
基本语法
正则表达式是表达文本模式的方法。
- .:匹配任何单个字符。
- ?:上一项是可选的,最多匹配一次。
- *:前一项将被匹配零次或多次。
- +:前一项将被匹配一次或多次。
- {N}:上一项完全匹配N次。
- {N,}:前一项匹配N次或多次。
- {N,M}:前一项至少匹配N次,但不超过M次。
- --:表示范围,如果它不是列表中的第一个或最后一个,也不是列表中某个范围的终点。
- ^:匹配行首的空字符串;也代表不在列表范围内的字符。
- $:匹配行尾的空字符串。
- \b:匹配单词边缘的空字符串。
- \B:匹配空字符串,前提是它不在单词的边缘。
- \<:匹配单词开头的空字符串。
- \>:匹配单词末尾的空字符串。
元字符
元字符是表示特殊函数的字符,包括以下这些^ $ . [ ] { } - ? * + ( ) | \\。除了元字符,其他字符在正则表达式中,都表示原来的含义。
- .匹配任意字符,但不含空字符
- ^匹配文本行开头
- $匹配文本行结尾
grep -h '.zip' dirlist*.txt
上面命令在文件中查找包含正则表达式“.zip”的文本行。注意,上面命令不会匹配zip程序,因为zip只有三个字符,而.zip要求四个字符。
grep -h '^zip' dirlist*.txt
grep -h 'zip$' dirlist*.txt
上面命令分别在文件列表中搜索行首,行尾以及行首和行尾同时包含字符串“zip”(例如,zip 独占一行)的匹配行。 注意正则表达式‘^$’(行首和行尾之间没有字符)会匹配空行。
方括号
方括号之中的字符,表示可以任意匹配其中的一个。
grep -h '[bg]zip' dirlist*.txt
上面命令匹配包含字符串“bzip”或者“gzip”的任意行。
注意,元字符放入方括号之中,会失去其特殊含义。但有两种情况除外,^在方括号的开头,表示否定,否则只是一个普通字符,表示原义。
grep -h '[^bg]zip' dirlist*.txt
上面命令匹配不以b或g开头的zip字符串。注意,上面命令不会匹配zip,因为一个否定的字符集仍然要求存在一个字符。
-在方括号之中表示一个字符区域。
grep -h '^[A-Z]' dirlist*.txt
上面命令匹配所有以大写字母开头的文本行。类似的,^[A-Za-z0-9]表示以大写字母、小写字母、数字开头的文本行。
注意,连字号如果不构成一个字符区域,则表示其本来的含义。
grep -h '[-AZ]' dirlist*.txt
上面命令匹配包含一个连字符,或一个大写字母“A”,或一个大写字母“Z”的文件名。
预定义字符类
由于locale设置不同,Shell展开正则表达式[A-Z]时,可能不是解释为所有大写字母,而是解释为包括所有字母的字典顺序。
ls /usr/sbin/[A-Z]*
上面命令在某些发行版里面,会返回所有大写字母或小写字母开头的文件。
为了避免这个问题,可以使用正则表达式的预定义字符类。
- [:alnum:]字母数字字符。在 ASCII 中,等价于:- [A-Za-z0-9]
- [:word:]与- [:alnum:]相同, 但增加了下划线字符。
- [:alpha:]字母字符。在 ASCII 中,等价于- [A-Za-z]
- [:blank:]包含空格和 tab 字符。
- [:cntrl:]ASCII 的控制码。包含了0到31,和127的 ASCII 字符。
- [:digit:]数字0到9
- [:graph:]可视字符。在 ASCII 中,它包含33到126的字符。
- [:lower:]小写字母。
- [:punct:]标点符号字符。
- [:print:]可打印的字符。等于- [:graph:]中的所有字符,再加上空格字符。
- [:space:]空白字符,包括空格,tab,回车,换行,vertical tab, 和 form feed.在 ASCII 中, 等价于- [ \t\r\n\v\f]
- [:upper:]大写字母。
- [:xdigit:]用来表示十六进制数字的字符。在 ASCII 中,等价于- [0-9A-Fa-f]
ls /usr/sbin/[[:upper:]]*
上面命令返回所有大写字母开头的文件名。
选择
|表示匹配一系列字符串之中的一个。注意与方括号区分,方括号表示匹配一系列字符之中的一个。
$ echo "AAA" | grep -E 'AAA|BBB'
AAA
$ echo "BBB" | grep -E 'AAA|BBB'
BBB
$ echo "CCC" | grep -E 'AAA|BBB'
$
上面代码中,AAA|BBB表示匹配字符串AAA或者是字符串BBB。grep程序使用-E参数,表示按照正则表达式规则匹配。并且,这个正则表达式放在单引号之中,为的是阻止Shell把|解释为管道操作符。
|可以多个连用,也可以与其他正则规则结合使用。
echo "AAA" | grep -E 'AAA|BBB|CCC'
grep -Eh '^(bz|gz|zip)' dirlist*.txt
量词操作符
量词操作符表示一个元素被匹配的次数。
- ?匹配前面的元素出现0次或1次
- *匹配前面的元素出现0次或多次
- +匹配前面的元素出现1次或多次
- {n}匹配前面的元素出现了- n次
- {n,m}匹配前面的元素它至少出现了- n次,但是不多于- m次
- {n,}匹配前面的元素至少出现了- n次
- {,m}匹配前面的元素,如果它出现的次数不多于 m 次。
扩展用法
非捕获匹配
- 
    (?:pattern)
 ()表示捕获分组,()会把每个分组里的匹配的值保存起来, 从左向右, 以分组的左括号为标志, 第一个出现的分组的组号为1, 第二个为2, 以此类推
 (?:)表示非捕获分组, 和捕获分组唯一的区别在于, 非捕获分组匹配的值不会保存起来
- 
    (?=pattern)
 正向肯定预查(look ahead positive assert), 匹配pattern前面的位置. 这是一个非获取匹配, 也就是说, 该匹配不需要获取供以后使用.
 简单说, 以xxx(?=pattern)为例, 就是捕获以pattern结尾的内容xxx
 例如,Windows(?=95|98|NT|2000)能匹配Windows2000中的Windows, 但不能匹配Windows3.1中的Windows. 预查不消耗字符, 也就是说, 在一个匹配发生后, 在最后一次匹配之后立即开始下一次匹配的搜索, 而不是从包含预查的字符之后开始.
- 
    (?!pattern)
 正向否定预查(negative assert), 在任何不匹配pattern的字符串开始处匹配查找字符串. 这是一个非获取匹配, 也就是说, 该匹配不需要获取供以后使用.
 简单说, 以xxx(?!pattern)为例, 就是捕获不以pattern结尾的内容xxx
 例如Windows(?!95|98|NT|2000)能匹配Windows3.1中的Windows, 但不能匹配Windows2000中的Windows. 预查不消耗字符, 也就是说, 在一个匹配发生后, 在最后一次匹配之后立即开始下一次匹配的搜索, 而不是从包含预查的字符之后开始.
- 
    (?<=pattern)
 反向(look behind)肯定预查, 与正向肯定预查类似, 只是方向相反.
 简单说, 以(?<=pattern)xxx为例, 就是捕获以pattern开头的内容xxx.
 例如,(?<=95|98|NT|2000)Windows能匹配2000Windows中的Windows, 但不能匹配3.1Windows中的Windows.
- 
    (?<!pattern)
 简单说, 以(?<!pattern)xxx为例, 就是捕获不以pattern开头的内容xxx.
 反向否定预查, 与正向否定预查类似, 只是方向相反.
 例如(?<!95|98|NT|2000)Windows能匹配3.1Windows中的Windows, 但不能匹配2000Windows中的Windows.
如要保留某行
- 提取匹配的文字
<FieldNo>9</FieldNo>  
<FieldName>Setup_Time_Max</FieldName>  
<FieldType>SQL_FLOAT</FieldType>  
需要提取 <FieldName>(\w+)</FieldName> 中的内容
使用 ^((?!<FieldName>(\w+)</FieldName>).)*$ 提取<FieldName>中的内容, 然后<FieldName>(\w+)</FieldName>替换为$1将内容提取出来
更通用的^(?!.*?yourwords).*$, 匹配没有 yourwords 的一整行
其他用法
- ([A-Za-z]+) +\1匹配重复单词
- /(?<=\d)(?=(\d\d\d)+\b)/g替换为- ,将数字- 1234567替换为- 1,234,567