正则表达式 (regex) 的快速参考,包括符号、范围、分组、断言和一些帮助您入门的示例模式。
字符类
[abc] | 单个字符:a、b 或 c |
[^abc] | 一个字符,除了:a、b 或 c |
[a-z] | 范围内的一个字符:az |
[^a-z] | 不在范围内的字符:az |
[0-9] | 范围内的数字:0-9 |
[a-zA-Z] | 范围内的一个字符: az 或 AZ |
[a-zA-Z0-9] | 范围内的一个字符: az、AZ 或 0-9 |
量词
a? | 零个或一个 |
a* | 零个或多个 |
a+ | 一个或多个 |
[0-9]+ | 0-9 中的一项或多项 |
a{3} | 正好 3 个 |
a{3,} | 3个或更多 |
a{3,6} | 介于 3 和 6 之间 |
a* | 贪婪量词 |
a*? | 惰性量词 |
a*+ | 所有格量词 |
转义这些特殊字符 \
. | 任意单个字符 |
\s | 任何空白字符 |
\S | 任何非空白字符 |
\d | 任意数字,同[0-9] |
\D | 任何非数字,同[^0-9] |
\w | 任何单词字符 |
\W | 任何非单词字符 |
\X | 任何 Unicode 序列,包括换行符 |
\C | 匹配一个数据单元 |
\R | Unicode 换行符 |
\v | 垂直空白字符 |
\V | \v 的否定 - 除了换行符和垂直制表符之外的任何东西 |
\h | 水平空白字符 |
\H | \h 的否定 |
\K | 重置匹配 |
\n | 匹配第 n 个子模式 |
\pX | Unicode 属性 X |
\p{...} | Unicode 属性或脚本类别 |
\PX | \pX 的否定 |
\P{...} | \p 的否定 |
\Q...\E | 引用; 视为文字 |
\k<name> | 匹配子模式 name |
\k'name' | 匹配子模式 name |
\k{name} | 匹配子模式 name |
\gn | 匹配第 n 个子模式 |
\g{n} | 匹配第 n 个子模式 |
\g<n> | 递归第 n 个捕获组 |
\g'n' | 递归第 n 个捕获组。 |
\g{-n} | 匹配第 n 个相对前一个子模式 |
\g<+n> | 递归第 n 个相对即将到来的子模式 |
\g'+n' | 匹配第 n 个相对即将到来的子模式 |
\g'letter' | 递归命名捕获组 letter |
\g{letter} | 匹配先前命名的捕获组 letter |
\g<letter> | 递归命名捕获组 letter |
\xYY | 十六进制 YY |
\x{YYYY} | 十六进制字符 YYYY |
\ddd | 八进制字符ddd |
\cY | 控制字符 Y |
[\b] | 退格字符 |
\ | 使任何字符文字 |
锚
\G | 比赛开始 |
^ | 字符串的开始 |
$ | 字符串结束 |
\A | 字符串的开始 |
\Z | 字符串结束 |
\z | 字符串的绝对结尾 |
\b | 一个词的边界 |
\B | 非词边界 |
替换
\0 | 完整的比赛内容 |
\1 | 捕获组 1 中的内容 |
$1 | 捕获组 1 中的内容 |
${foo} | 捕获组中的内容 foo |
\x20 | 十六进制替换值 |
\x{06fa} | 十六进制替换值 |
\t | 标签 |
\r | 回车 |
\n | 新队 |
\f | 换页 |
\U | 大写转换 |
\L | 小写转换 |
\E | 终止任何转换 |
组构造
(...) | 捕获所有封闭的东西 |
(a|b) | 匹配 a 或 b |
(?:...) | 匹配包含的所有内容 |
(?>...) | 原子组(非捕获) |
(?|...) | 重复的子模式组号 |
(?#...) | 评论 |
(?'name'...) | 命名捕获组 |
(?<name>...) | 命名捕获组 |
(?P<name>...) | 命名捕获组 |
(?imsxXU) | 内联修饰符 |
(?(DEFINE)...) | 在使用之前预定义模式 |
断言
(?(1)yes|no) | 条件语句 |
(?(R)yes|no) | 条件语句 |
(?(R#)yes|no) | 递归条件语句 |
(?(R&name)yes|no) | 条件语句 |
(?(?=...)yes|no) | 有条件的前瞻 |
(?(?<=...)yes|no) | 后视条件 |
环视
(?=...) | 正向预测 |
(?!...) | 负前瞻 |
(?<=...) | 正面回顾 |
(?<!...) | 负面回顾 |
Lookaround 允许您在主模式之前 (lookbehind) 或之后 (lookahead) 匹配一个组,而不将其包含在结果中。
标志/修饰符
g | 全球的 |
m | 多线 |
i | 不区分大小写 |
x | 忽略空格 |
s | 单线 |
u | 统一码 |
X | 扩展 |
U | 不贪心 |
A | 锚 |
J | 重复的组名 |
递归
(?R) | 递归整个模式 |
(?1) | 递归第一个子模式 |
(?+1) | 递归第一个相对子模式 |
(?&name) | 递归子模式 name |
(?P=name) | 匹配子模式 name |
(?P>name) | 递归子模式 name |
POSIX 字符类
控制动词
(*ACCEPT) | 控制动词 |
(*FAIL) | 控制动词 |
(*MARK:NAME) | 控制动词 |
(*COMMIT) | 控制动词 |
(*PRUNE) | 控制动词 |
(*SKIP) | 控制动词 |
(*THEN) | 控制动词 |
(*UTF) | 图案修饰符 |
(*UTF8) | 图案修饰符 |
(*UTF16) | 图案修饰符 |
(*UTF32) | 图案修饰符 |
(*UCP) | 图案修饰符 |
(*CR) | 换行修饰符 |
(*LF) | 换行修饰符 |
(*CRLF) | 换行修饰符 |
(*ANYCRLF) | 换行修饰符 |
(*ANY) | 换行修饰符 |
\R | 换行修饰符 |
(*BSR_ANYCRLF) | 换行修饰符 |
(*BSR_UNICODE) | 换行修饰符 |
(*LIMIT_MATCH=x) | 正则表达式引擎修饰符 |
(*LIMIT_RECURSION=d) | 正则表达式引擎修饰符 |
(*NO_AUTO_POSSESS) | 正则表达式引擎修饰符 |
(*NO_START_OPT) | 正则表达式引擎修饰符 |
正则表达式示例
字符匹配
ring | 匹配 ring springboard等 |
. | 匹配 a, 9, + 等等。 |
h.o | 匹配 hoo, h2o, h/o 等等。 |
ring\? | 匹配 ring? |
\(quiet\) | 匹配 (quiet) |
c:\\windows | 匹配 c:\windows |
使用\
搜索这些特殊字符:
[ \ ^ $ . | ? * + ( ) { }
可替代方案
cat|dog | 匹配 cat 或者 dog |
id|identity | 匹配 id 或者 identity |
identity|id | 匹配 id 或者 identity |
当备选方案重叠时,从长到短排序
字符块匹配
[aeiou] | 匹配任何元音 |
[^aeiou] | 匹配一个非元音 |
r[iau]ng | 匹配 ring, wrangle, sprung, 等等。 |
gr[ae]y | 匹配 gray 或者 |
[a-zA-Z0-9] | 匹配任何字母或数字 |
在[ ]
总是逃避. \ ]
有时^ - .
特殊字符匹配
\w | “单词”字符 (字母、数字或下划线) |
\d | 数字 |
\s | 空格 (空格、制表符、vtab、换行符) |
\W, \D, or \S | 不是单词、数字或空格 |
[\D\S] | 表示不是数字或空格,两者都匹配 |
[^\d\s] | 禁止数字和空格 |
事件匹配
colou?r | 匹配 color 或者 colour |
[BW]ill[ieamy's]* | 匹配 Bill, Willy, William's 等等。 |
[a-zA-Z]+ | 匹配 1 个或多个字母 |
\d{3}-\d{2}-\d{4} | 匹配 SSN |
[a-z]\w{1,7} | 匹配 UW NetID |
贪婪匹配和懒惰匹配
* + {n,} 贪婪的 | 尽可能匹配 |
<.+> | 找到 1 个大匹配 <b>粗体</b> |
*? +? {n,}? 懒惰的 | 尽量少搭配 |
<.+?> | 在 < 中找到 2 个匹配项 乙 >粗体< /b > |
匹配范围
\b | "单词”边缘(在非“单词”字符旁边) |
\bring | 单词以“ring”开头,例如 铃声 |
ring\b | 单词以“ring”结尾,例如 春天 |
\b9\b | 匹配单个数字 9 ,而不是 19、91、99 等。 |
\b[a-zA-Z]{6}\b | 匹配 6 个字母的单词 |
\B | 不是字边 |
\Bring\B | 匹配 springs 和 wringer
|
^\d*$ | 整个字符串必须是数字 |
^[a-zA-Z]{4,20}$ | 字符串必须有 4-20 个字母 |
^[A-Z] | 字符串必须以大写字母开头 |
[\.!?"')]$ | 字符串必须以终结符结尾 |
修饰匹配
(?i) [a-z]*(?-i) | 忽略大小写 ON / OFF |
(?s) .*(?-s) | 匹配多行(导致 . 匹配换行符) |
(?m) ^.*;$(?-m) | ^ & $ 匹配行而不是整个字符串 |
(?x) | #free-spacing 模式,此 EOL 注释被忽略 |
(?-x) | 自由空间模式关闭 |
/regex/ismx | 整个字符串的修改模式 |
组匹配
(in\|out)put | 匹配 input 或者 output |
\d{5}(-\d{4})? | 美国邮政编码(“+4”可选) |
如果组后匹配失败,解析器会尝试每个替代方案。
可能导致灾难性的回溯。
反向引用
(to) (be) or not \1 \2 | 匹配 生存还是毁灭 |
([^\s])\1{2} | 匹配非空格,然后再重复两次 aaa , ... |
\b(\w+)\s+\1\b | 匹配双字 |
非捕获组
on(?:click\|load) | 比...快:
on(click\|load) |
尽可能使用非捕获或原子组
原子组
(?>red\|green\|blue) | 比非捕获更快 |
(?>id\|identity)\b | 匹配 id, 但不是 identity
|
“id”匹配,但\b
在原子组之后失败,解析器不会回溯到组以重试“身份”
如果替代品重叠,则从长到短排序。
周围匹配
(?= ) | 向前看,如果你能提前找到 |
(?! ) | 向前看,如果你不能提前找到 |
(?<= ) | 回头看,如果你能找到后面 |
(?<! ) | 回头看,如果你找不到后面 |
\b\w+?(?=ing\b) | 匹配 warbling, string, fish ing,... |
\b(?!\w+ing\b)\w+\b | 不以“ing”结尾的单词 |
(?<=\bpre).*?\b | 匹配 pretend,present,prefix,... |
\b\w{3}(?<!pre)\w*?\b | 不以“pre”开头的单词 |
\b\w+(?<!ing)\b | 匹配不以“ing”结尾的单词 |
If-then-else
匹配 "Mr." 或者 "Ms." 如果单词“her”在字符串后面
M(?(?=.*?\bher\b)s|r)\.
需要环视 if
条件
Python 中的正则表达式
入门
导入正则表达式模块
import re
例子
re.search()
>>> sentence = 'This is a sample string' >>> bool(re.search(r'this', sentence, flags=re.I)) True >>> bool(re.search(r'xyz', sentence)) False
re.findall()
>>> re.findall(r'\bs?pare?\b', 'par spar apparent spare part pare') ['par', 'spar', 'spare', 'pare'] >>> re.findall(r'\b0*[1-9]\d{2,}\b', '0501 035 154 12 26 98234') ['0501', '154', '98234']
re.finditer()
>>> m_iter = re.finditer(r'[0-9]+', '45 349 651 593 4 204') >>> [m[0] for m in m_iter if int(m[0]) < 350] ['45', '349', '4', '204']
re.split()
>>> re.split(r'\d+', 'Sample123string42with777numbers') ['Sample', 'string', 'with', 'numbers']
re.sub()
>>> ip_lines = "catapults\nconcatenate\ncat" >>> print(re.sub(r'^', r'* ', ip_lines, flags=re.M)) * catapults * concatenate * cat
重新编译()
>>> pet = re.compile(r'dog') >>> type(pet) <class '_sre.SRE_Pattern'> >>> bool(pet.search('They bought a dog')) True >>> bool(pet.search('A cat crossed their path')) False
方法
re.findall | 返回包含所有匹配项的列表 |
re.finditer | 返回一个可迭代的匹配对象(每个匹配一个) |
re.search | 如果字符串中的任何位置都匹配,则返回一个 Match 对象 |
re.split | 返回一个列表,其中字符串在每次匹配时被拆分 |
re.sub | 用字符串替换一个或多个匹配项 |
re.compile | 编译正则表达式模式以备后用 |
re.escape | 返回所有非字母数字反斜杠的字符串 |
Flags
re.I | re.IGNORECASE | 忽略大小写 |
re.M | re.MULTILINE | 多线 |
re.L | re.LOCALE | 使\w , \b ,\s 语言环境相关 |
re.S | re.DOTALL | 点匹配所有(包括换行符) |
re.U | re.UNICODE | 使\w , \b , \d , \s unicode 依赖 |
re.X | re.VERBOSE | 可读风格 |
JavaScript 中的正则表达式
test()
let textA = 'I like APPles very much'; let textB = 'I like APPles'; let regex = /apples$/i // Output: false console.log(regex.test(textA)); // Output: true console.log(regex.test(textB));
search()
let text = 'I like APPles very much'; let regexA = /apples/; let regexB = /apples/i; // Output: -1 console.log(text.search(regexA)); // Output: 7 console.log(text.search(regexB));
exec()
let text = 'Do you like apples?'; let regex= /apples/; // Output: apples console.log(regex.exec(text)[0]); // Output: Do you like apples? console.log(regex.exec(text).input);
match()
let text = 'Here are apples and apPleS'; let regex = /apples/gi; // Output: [ "apples", "apPleS" ] console.log(text.match(regex));
split()
let text = 'This 593 string will be brok294en at places where d1gits are.'; let regex = /\d+/g // Output: [ "This ", " string will be brok", "en at places where d", "gits are." ] console.log(text.split(regex))
matchAll()
let regex = /t(e)(st(\d?))/g; let text = 'test1test2'; let array = [...text.matchAll(regex)]; // Output: ["test1", "e", "st1", "1"] console.log(array[0]); // Output: ["test2", "e", "st2", "2"] console.log(array[1]);
replace()
let text = 'Do you like aPPles?'; let regex = /apples/i // Output: Do you like mangoes? let result = text.replace(regex, 'mangoes'); console.log(result);
replaceAll()
let regex = /apples/gi; let text = 'Here are apples and apPleS'; // Output: Here are mangoes and mangoes let result = text.replaceAll(regex, "mangoes"); console.log(result);
PHP 中的正则表达式
方法
preg_match() | 执行正则表达式匹配 |
preg_match_all() | 执行全局正则表达式匹配 |
preg_replace_callback() | 使用回调执行正则表达式搜索和替换 |
preg_replace() | 执行正则表达式搜索和替换 |
preg_split() | 按正则表达式模式拆分字符串 |
preg_grep() | 返回匹配模式的数组条目 |
preg_replace
$str = "Visit Microsoft!"; $regex = "/microsoft/i"; // Output: Visit QuickRef! echo preg_replace($regex, "QuickRef", $str);
preg_match
$str = "Visit QuickRef"; $regex = "#quickref#i"; // Output: 1 echo preg_match($regex, $str);
preg_matchall
$regex = "/[a-zA-Z]+ (\d+)/"; $input_str = "June 24, August 13, and December 30"; if (preg_match_all($regex, $input_str, $matches_out)) { // Output: 2 echo count($matches_out); // Output: 3 echo count($matches_out[0]); // Output: Array("June 24", "August 13", "December 30") print_r($matches_out[0]); // Output: Array("24", "13", "30") print_r($matches_out[1]); }
preg_grep
$arr = ["Jane", "jane", "Joan", "JANE"]; $regex = "/Jane/"; // Output: Jane echo preg_grep($regex, $arr);
preg_split
$str = "Jane\tKate\nLucy Marion"; $regex = "@\s@"; // Output: Array("Jane", "Kate", "Lucy", "Marion") print_r(preg_split($regex, $str));
Java 中的正则表达式
样式
第一种方式
Pattern p = Pattern.compile(".s", Pattern.CASE_INSENSITIVE); Matcher m = p.matcher("aS"); boolean s1 = m.matches(); System.out.println(s1); // Outputs: true
第二种方式
oolean s2 = Pattern.compile("[0-9]+").matcher("123").matches(); System.out.println(s2); // Outputs: true
第三种方式
boolean s3 = Pattern.matches(".s", "XXXX"); System.out.println(s3); // Outputs: false
模式字段
CANON_EQ | 规范等价 |
CASE_INSENSITIVE | 不区分大小写的匹配 |
COMMENTS | 允许空格和注释 |
DOTALL | Dotall 模式 |
MULTILINE | 多行模式 |
UNICODE_CASE | Unicode 感知大小写折叠 |
UNIX_LINES | Unix 线路模式 |
方法
Pattern
- Pattern compile(String regex [, int flags])
- boolean matches([String regex, ] CharSequence input)
- String[] split(String regex [, int limit])
- String quote(String s)
Matcher
- int start([int group | String name])
- int end([int group | String name])
- boolean find([int start])
- String group([int group | String name])
- Matcher reset()
String
- boolean matches(String regex)
- String replaceAll(String regex, String replacement)
- String[] split(String regex[, int limit])
还有更多的方法...
例子
替换语句:
String regex = "[A-Z\n]{5}$"; String str = "I like APP\nLE"; Pattern p = Pattern.compile(regex, Pattern.MULTILINE); Matcher m = p.matcher(str); // Outputs: I like Apple! System.out.println(m.replaceAll("pple!"));
所有匹配项的数组:
String str = "She sells seashells by the Seashore"; String regex = "\\w*se\\w*"; Pattern p = Pattern.compile(regex, Pattern.CASE_INSENSITIVE); Matcher m = p.matcher(str); List<String> matches = new ArrayList<>(); while (m.find()) { matches.add(m.group()); } // Outputs: [sells, seashells, Seashore] System.out.println(matches);
MySQL 中的正则表达式
方法
REGEXP | 字符串是否匹配正则表达式 |
REGEXP_INSTR() | 匹配正则表达式的子字符串的起始索引 (注意:仅限 MySQL 8.0+) |
REGEXP_LIKE() | 字符串是否匹配正则表达式 (注意:仅限 MySQL 8.0+) |
REGEXP_REPLACE() | 替换匹配正则表达式的子字符串 (注意:仅限 MySQL 8.0+) |
REGEXP_SUBSTR() | 返回匹配正则表达式的子字符串 (注意:仅限 MySQL 8.0+) |
REGEXP
expr REGEXP pat
例子
mysql> SELECT 'abc' REGEXP '^[a-d]'; 1 mysql> SELECT name FROM cities WHERE name REGEXP '^A'; mysql> SELECT name FROM cities WHERE name NOT REGEXP '^A'; mysql> SELECT name FROM cities WHERE name REGEXP 'A|B|R'; mysql> SELECT 'a' REGEXP 'A', 'a' REGEXP BINARY 'A'; 1 0
REGEXP_REPLACE
REGEXP_REPLACE(expr, pat, repl[, pos[, occurrence[, match_type]]])
例子
mysql> SELECT REGEXP_REPLACE('a b c', 'b', 'X'); a X c mysql> SELECT REGEXP_REPLACE('abc ghi', '[a-z]+', 'X', 1, 2); abc X
REGEXP_SUBSTR
REGEXP_SUBSTR(expr, pat[, pos[, occurrence[, match_type]]])
例子
mysql> SELECT REGEXP_SUBSTR('abc def ghi', '[a-z]+'); abc mysql> SELECT REGEXP_SUBSTR('abc def ghi', '[a-z]+', 1, 3); ghi
REGEXP_LIKE
REGEXP_LIKE(expr, pat[, match_type])
例子
mysql> SELECT regexp_like('aba', 'b+') 1 mysql> SELECT regexp_like('aba', 'b{2}') 0 mysql> # i: case-insensitive mysql> SELECT regexp_like('Abba', 'ABBA', 'i'); 1 mysql> # m: multi-line mysql> SELECT regexp_like('a\nb\nc', '^b$', 'm'); 1
REGEXP_INSTR
REGEXP_INSTR(expr, pat[, pos[, occurrence[, return_option[, match_type]]]])
例子
mysql> SELECT regexp_instr('aa aaa aaaa', 'a{3}'); 2 mysql> SELECT regexp_instr('abba', 'b{2}', 2); 2 mysql> SELECT regexp_instr('abbabba', 'b{2}', 1, 2); 5 mysql> SELECT regexp_instr('abbabba', 'b{2}', 1, 3, 1); 7