文本查找
Wildcard (Glob)
In computer programming, glob patterns specify sets of filenames with wildcard characters.
*:匹配任意数量字符;
?:匹配单个字符;
[abc]:匹配集合中的单个字符;[!...]反向匹配。
[a-z]:匹配范围内的单个字符。
SQL通配符
SQL LIKE语句:_对应?;%对应*;不支持[...]。
glob (programming) - Wikipedia
正则表达式(Regular Expression)
正则表达式定义了字符串的模式,可以用来搜索、编辑或处理文本。
正则表达式并不仅限于某一种编程语言,但是在每种语言中有细微的差别。
表达式语法
正则表达式是一个字符串,其中包含:
- 普通字符、转义字符;
- 字符集合;
- 匹配位置,位于匹配内容之前;
- 匹配次数,位于匹配内容之后。
- 运算符:
():优先级运算符,产生捕获组;x|y|z:匹配其中一项,从左至右依次尝试;使用(...|...|...)将选择内容括起来以免产生歧义。
正则表达式类型
基本正则表达式(BRE)与扩展正则表达式(ERE)的主要区别是对特殊字符的解释:BRE需要使用\表示特殊字符,而ERE则恰好相反(使用\将特殊字符转为普通字符)。
- BRE:
\+、\?、\{...\}、\(...\)、\|; - ERE:
+、?、{...}、(...)、|;
BRE和ERE对其他转义字符的处理方式一致,即\CHAR。
PRE在ERE基础上定义了许多扩展功能,如预定义的匹配集合、非捕获元等。
匹配位置
^:扫描行的开始 如:^word匹配所有以word开头的行。
$:扫描行的结束 如:word$匹配所有以word结尾的行。
当未指定匹配位置时,可在文本任何位置进行匹配。注意某些编程语言(例如Python)中提供的
match方法限制了从开始位置匹配。文本行的开始和结束可能包含空白字符,执行边界匹配时需要考虑。
匹配次数
| 表达式 | 说明 |
|---|---|
(...){n} | 表达式重复n次 |
(...){m,n}(...){m,} | 表达式至少重复m次(最多重复n次) |
(...)? | 匹配表达式0或者1次,相当于{0,1}(通配符) |
(...)+ | 前面的表达式至少出现1次,相当于{1,} |
(...)* | 表达式不出现或出现任意次,相当于{0,}(正则表达式中不代表匹配任意字符) |
(...)*?(...)+? | 匹配尽可能多的文本(非贪婪模式)。 |
(...)?? | 匹配尽可能少的文本(非贪婪模式)*。 |
非捕获选择
用圆括号将所有选择项括起来,相邻的选择项之间用|分隔。但用圆括号会有一个副作用,使相关的匹配会被捕获(group),此时可用(?:A|B|...)(非捕获元)放在第一个选项前来消除这种副作用(仅PRE支持)。
捕获组的内容可在表达式后续内容中进行引用:([0-9]{3}),(\w{4})\1\2(\1和\2分别代表之前出现过的捕获组内容)。捕获组的==索引顺序:从左至右,由外至内==;
?=和?!:正向/反向预查,在任何开始匹配圆括号内的正则表达式模式的位置来匹配搜索字符串,后者为负向预查,在任何开始不匹配该正则表达式模式的位置来匹配搜索字符串。
消费
当字符串的内容与模式匹配成功后,匹配内容及之前的内容将被消耗,后续匹配将从剩余字串继续匹配。
字符
字符集合
| 预定义集合表达式 | 说明 |
|---|---|
\d/\D | 0~9之间的任意数字;\D为补集* |
\w/\W | 字母(包括非英语文字)、数字或下划线,\W为\w的补集; |
\s/\S | ==空白字符==:包括空格、制表符、换行符 |
\b | 文字字符边界(boundary between a \w and a \W character)。注意:两个非文字字符之间没有边界。 |
. | 除换行符之外的任意一个字符 |
*:\d,\D是PRE扩展,对于grep/sed等程序,如果使用ERE/BRE,可使用[:digit:]代替。
各实现还定义了扩展的字符集合。
自定义字符集合
[...]用于自定义匹配范围,其中可以包括:
-
普通字符:
[ab5@],[a-z],[0-9],[a-zA-z0-9]; -
预定义集合:
[\d.+],[[:digit:]a-z]; -
排除运算:
[^abc],除a,b,c以外的任意字符; -
范围运算:
[f-k],f~k之间的任意字符; -
排除范围:
[^A-F0~3],A~F以及0~3以外的任意字符。
正则表达式的特殊符号(如.+*),被包含到中括号中,则失去特殊意义,除了^,-之外。
:是普通字符。
转义字符
| 序列 | 代表字符 | 序列 | 代表字符 |
|---|---|---|---|
\n | 换行符 | \\ | 反斜线 |
\t | 制表符* | \r | 回车符 |
\f | 换页符 | \v | 垂直制表符 |
\^,\$,\.,\*,,\[,\], \- | 特殊字符 | \xn | 匹配十六进制码n表示的字符 |
*:\n和\\是通用的,其他特殊序列如\t则可能被解释为字符t。
注意:部分转移字符(例如\n、\\等)在编程语言的字符串中首先会被作为转义字符处理,因此在正则表达式中要额外使用\消除编程语言中的转义处理。在Python中可以使用原始字符串类型,以避免对字符串中的\的解释。
regexp_str = r'hello\.world\\'
regexp_str = 'hello\\.world\\\\'
应用
IP地址
Simple regex to check for an IP address:
'^(?:[0-9]{1,3}\.){3}[0-9]{1,3}$'
Accurate regex to check for an IP address:
'^(?:(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.){3}(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)$'
Simple regex to extract IP addresses from longer text:
'\b(?:[0-9]{1,3}\.){3}[0-9]{1,3}\b' # \b for word space
Accurate regex to extract IP addresses from longer text:
'(?:(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.){3}(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)'
(?:xxx)在grep中导致无匹配输出,在Pythonre中可以正常输出匹配。
URL
re.sub('https://.*?/', '', data, count=1) # 获取URI
实现
预定义字符集
grep and sed
| 集合表达式 | 说明 | 集合表达式 | 说明 |
|---|---|---|---|
[:ascii:] | ASCII字符 | [:cntrl:] | ASCII控制字符 |
[:graph:] | 非控制/空格字符 | [:blank:] | 空格或制表符 |
[:space:] | 空白字符(包括垂直制表符) | [:punct:] | 标点符号 |
[:digit:] | 数字 | [:xdigit:] | 十六进制数字 |
[:alpha:] | 字母 | [:alnum:] | 英语字母与数字 |
[:lower:] | 小写字母 | [:print:] | 可打印字符(包括非ASCII字符) |
[:upper:] | 大写字母 |
python
| 集合表达式 | 说明 |
|---|---|
\NNN | 匹配第$N$个捕获组内容([...]中无效) |
\A/\Z | 匹配文本开始(^)和结束($); |