阅读(12) (0)

正则表达式备忘单

2021-08-31 10:44:04 更新

正则表达式 (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 字符类

[[:alnum:]] [0-9A-Za-z] 字母和数字
[[:alpha:]] [A-Za-z] 信件
[[:ascii:]] [\x00-\x7F] ASCII 码 0-127
[[:blank:]] [\t ] 仅空格或制表符
[[:cntrl:]] [\x00-\x1F\x7F] 控制字符
[[:digit:]] [0-9] 十进制数字
[[:graph:]] [[:alnum:][:punct:]] 可见字符(不是空格)
[[:lower:]] [a-z] 小写字母
[[:print:]] [ -~] == [ [:graph:]] 可见字符
[[:punct:]] [!"#$%&’()*+,-./:;<=>?@[]^_`{|}~] 可见标点符号
[[:space:]] [\t\n\v\f\r ] 空白
[[:upper:]] [A-Z] 大写字母
[[:word:]] [0-9A-Za-z_] 文字字符
[[:xdigit:]] [0-9A-Fa-f] 十六进制数字
[[:<:]] [\b(?=\w)] 词的开头
[[:>:]] [\b(?<=\w)] 词尾

控制动词

(*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
. 匹配  a9+ 等等。
h.o 匹配 hooh2oh/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));
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