Deprecated
: htmlspecialchars(): Passing null to parameter #1 ($string) of type string is deprecated in
/www/wwwroot/testblog.58heshihu.com/var/Widget/Archive.php
on line
1057
首页
关于
Search
1
给你10个市场数据调研报告的免费下载网站!以后竞品数据就从这里找!
182 阅读
2
php接口优化 使用curl_multi_init批量请求
144 阅读
3
《从菜鸟到大师之路 ElasticSearch 篇》
107 阅读
4
2024年备考系统架构设计师
104 阅读
5
PHP 文件I/O
92 阅读
php
thinkphp
laravel
工具
开源
mysql
数据结构
总结
思维逻辑
令人感动的创富故事
读书笔记
前端
vue
js
css
书籍
开源之旅
架构
消息队列
docker
教程
代码片段
redis
服务器
nginx
linux
科普
java
c
ElasticSearch
测试
php进阶
php基础
登录
Search
标签搜索
php函数
php语法
性能优化
安全
错误和异常处理
问题
vue
Composer
Session
缓存
框架
Swoole
api
并发
异步
正则表达式
php-fpm
mysql 索引
开发规范
协程
dafenqi
累计撰写
786
篇文章
累计收到
28
条评论
首页
栏目
php
thinkphp
laravel
工具
开源
mysql
数据结构
总结
思维逻辑
令人感动的创富故事
读书笔记
前端
vue
js
css
书籍
开源之旅
架构
消息队列
docker
教程
代码片段
副业
redis
服务器
nginx
linux
科普
java
c
ElasticSearch
测试
php进阶
php基础
页面
关于
搜索到
8
篇与
的结果
2024-03-20
正则表达式文章汇总
正则-调试/tag/正则表达式/菜鸟-正则表达式
2024年03月20日
13 阅读
0 评论
0 点赞
2023-10-13
《从菜鸟到大师之路 正则表达式 篇》
《从菜鸟到大师之路 正则表达式 篇》正则表达式是一个强大的文本匹配工具。但是,对于前端初学者来说,众多的符号和规则可能让人难以理解。其实,你不需要记住所有的正则表达式语法!本文将分享一些简单而实用的技巧,帮助理解正则表达式的核心概念,轻松使用正则表达式!一、基础入门概念正则表达式(Regular Expression,在代码中常简写为regex、regexp或RE)使用单个字符串来描述、匹配一系列符合某个句法规则的字符串搜索模式。搜索模式可用于文本搜索和文本替换。它用一系列字符定义搜索模式。正则表达式的用途 有很多,比如:表单输入验证;搜索和替换;过滤大量文本文件(如日志)中的信息;读取配置文件;网页抓取;处理具有一致语法的文本文件,例如 CSV。创建正则表达式的语法如下:/正则表达式主体/修饰符(可选) 先来看一个最基本的正则表达式:/处/,它只匹配到了字符串中的第一个“处”:这里,正则表达式的主体就是“处”,没有使用修饰符,我们会在后面来介绍正则表达式的修饰符。创建正则表达式的方式有两种:字面量:正则表达式直接放在/ /之中:const rex = /pattern/;构造函数:RegExp 对象表示正则表达式的一个实例:const rex = new RegExp("pattern"); 这两种方法的一大区别是对象的构造函数允许传递带引号的表达式,通过这种方式就可以动态创建正则表达式。通过这两种方法创建出来的 Regex 对象都具有相同的方法和属性:let RegExp1 = /a|b/ let RegExp2 = new RegExp('a|b') console.log(RegExp1) // 输出结果:/a|b/ console.log(RegExp2) // 输出结果:/a|b/ RegExp 实例实例方法RegExp 实例置了test()和exec() 这两个方法来校验正则表达式。下面来分别看一下这两个方法。(1)test()test()用于检测一个字符串是否匹配某个模式,如果字符串中含有匹配的文本,则返回 true,否则返回 false。const regex1 = /a/ig; const regex2 = /hello/ig; const str = "Action speak louder than words"; console.log(regex1.test(str)); // true console.log(regex2.test(str)); // false (2)exec()exec()用于检索字符串中的正则表达式的匹配。该函数返回一个数组,其中存放匹配的结果。如果未找到匹配,则返回值为 null。const regex1 = /a/ig; const regex2 = /hello/ig; const str = "Action speak louder than words"; console.log(regex1.exec(str)); // ['A', index: 0, input: 'Action speak louder than words', groups: undefined] console.log(regex2.exec(str)); // null 在当在全局正则表达式中使用 exec 时,每隔一次就会返回null,如图:这是怎么回事呢?MDN 的解释如下:在设置了 global 或 sticky 标志位的情况下(如 /foo/g or /foo/y),JavaScript RegExp 对象是有状态的。他们会将上次成功匹配后的位置记录在 lastIndex 属性中。使用此特性,exec() 可用来对单个字符串中的多次匹配结果进行逐条的遍历(包括捕获到的匹配),而相比之下, String.prototype.match() 只会返回匹配到的结果。为了解决这个问题,我们可以在运行每个exec命令之前将lastIndex赋值为 0:实例属性RegExp 实例还内置了一些属性,这些属性可以获知一个正则表达式的各方面的信息,但是用处不大。二、模式匹配关于正则表达式最复杂的地方就是如何编写正则规则了,下面就来看如何编写正则表达式。修饰符正则表达式的修饰符是一种可以在正则表达式模式中添加的标记,用于修改搜索模式的行为。这些修饰符通常以单个字符形式出现在正则表达式的末尾,并且可以通过在正则表达式模式前添加该字符来启用修饰符。常见的修饰符如下:g:表示全局模式,即运用于所有字符串;i:表示不区分大小写,即匹配时忽略字符串的大小写;m:表示多行模式,强制 $ 和 ^ 分别匹配每个换行符。最开始的例子中,字符串中有两个“处”,但是只匹配到了一个。这是因为正则表达式默认匹配第一个符合条件的字符。如果想要匹配所有符合条件的字符,就可以使用 g 修饰符:/处/g 这样就匹配到了所有符合条件的字符:当需要匹配引英文字符串,并且忽略字符串的字母大小写时,i 修饰符就派上用场了。先来看下面的表达式:/a/g 在进行匹配时,它匹配到了字符串中所有的 a 字符。但是最开始的 A 是没匹配到的,因为两者大小写不一致:那我们来添加上 i 修饰符:/a/gi 这时所有的 a 都被匹配到了,无论是大写还是小写,总共匹配到了三个 a:还有一个小疑问, 如果是对象构造函数的方式来构造正则表达式使,如何添加这些修饰符呢?其实很简单,只要将修饰符作为第二个参数传递给 构造函数就可以了:let regExp = new RegExp('[2b|^2b]', 'gi') console.log(regExp) // 输出结果:/[2b|^2b]/gi 字符集合如果我们想匹配 bat、cat 和 fat 这种类型的字符串该怎么办?可以通过使用字符集合来做到这一点,用 [] 表示,它会匹配包含的任意一个字符。这里就可以使用/[bcf]at/ig:可以看到,这里匹配到了字符串中的 bat、cat、fat。因为我们使用了 g 修饰符,所以匹配到了三个结果。当然,字符集也可以用来匹配数字:字符范围如果我们想要在字符串中匹配所有以 at 结尾的单词,最直接的方式是使用字符集,并在其中提供所有的字母。对于这种在一个范围中的字符, 就可以直接定义字符范围,用-表示。它用来匹配指定范围内的任意字符。这里就可以使用/[a-z]at/ig:可以看到,正则表达式按照我们的预期匹配了。常见的使用范围的方式如下:部分范围:[a-f],匹配 a 到 f 的任意字符;小写范围:[a-z],匹配 a 到 z 的任意字符;大写范围:[A-Z],匹配 A 到 Z 的任意字符;数字范围:[0-9],匹配 0 到 9 的任意字符;符号范围:[#$%&@];混合范围:[a-zA-Z0-9],匹配所有数字、大小写字母中的任意字符。数量字符如果想要匹配三个字母的单词,根据上面我们学到的字符范围,可以这样来写:[a-z][a-z][a-z] 这里我们匹配的三个字母的单词,那如果想要匹配10个、20个字母的单词呢?难道要一个个来写范围吗?有一种更好的方法就是使用花括号{}来表示,来看例子:可以看到,这里我们匹配到了所有连续5个字母的单词(包括超过5个字母的单词,不过只会匹配到前5个字母)。其实匹配重复字符的完整语法是这样的:{m,n},它会匹配前面一个字符至少 m 次至多 n 次重复,{m}表示匹配 m 次,{m,}表示至少 m 次。所以,当我们给5后面加上逗号时,就表示至少匹配五次:所以这里就匹配到了所有连续5个或5个以上的单词。当匹配次数为至少4次,至多5次时,匹配结果如下:除了可以使用大括号来匹配一定数量的字符,还有三个相关的模式:+:匹配前面一个表达式一次或者多次,相当于 {1,};*:匹配前面一个表达式0次或者多次,相当于 {0,};?:单独使用匹配前面一个表达式零次或者一次,相当于 {0,1},如果跟在量词*、+、?、后面的时候将会使量词变为非贪婪模式(尽量匹配少的字符),默认是使用贪婪模式。来看一个简单的例子,这里我们匹配的正则表达式为/a+/ig,结果如下:它和/a{1,}/ig的匹配结果是一样的:使用/[a-z]+/ig就可以匹配任意长度的纯字母单词:元字符使用元字符可以编写更紧凑的正则表达式模式。常见的元字符如下:\d:相当于[0-9],匹配任意数字;\D:相当于[^0-9];\w:相当于[0-9a-zA-Z],匹配任意数字、大小写字母和下划线;\W:相当于:[^0-9a-zA-Z];\s:相当于[\t\v\n\r\f],匹配任意空白符,包括空格,水平制表符\t,垂直制表符\v,换行符\n,回车符\r,换页符\f;\S:相当于[^\t\v\n\r\f],表示非空白符。来看一个简单的例子:这里使用\d来匹配任意数字、字母和下划线。这里就匹配到了7个连续四位的字符。特殊字符使用特殊字符可以编写更高级的模式表达式,常见的特殊字符如下:.:匹配除了换行符之外的任何单个字符;\:将下一个字符标记为特殊字符、或原义字符、或向后引用、或八进制转义符;|:逻辑或操作符;[^]:取非,匹配未包含的任意字符。来看一个简单的例子,如果我们使用 /ab*/ig 进行匹配,结果就如下:那我们就是想要匹配 * 怎么办?就可以使用 \ 对其进行转义:这样就只会匹配到 ab* 了。或匹配也很简单,来看例子,匹配规则为:/ab|cd/ig,匹配结果如下:这里就会匹配到字符串中所有 ab 和 cd 字符。那如果想要匹配 sabz 或者scdz呢?开头和结尾是相同的,只有中间的两个字符是可选的。其实只需要给中间的或部分加上括号就可以了:取非规则在范围中使用,来看例子:这里匹配到了所有非字母的字符。位置匹配如果我们想匹配字符串中以某些字符结尾的单词,以某些字符开头的单词该如何实现呢?正则表达式中提供了方法通过位置来匹配字符:\b:匹配一个单词边界,也就是指单词和空格间的位置;\B:匹配非单词边界;^:匹配开头,在多行匹配中匹配行开头;$:匹配结尾,在多行匹配中匹配行结尾;(?=p):匹配 p 前面的位置;(?!=p):匹配不是 p 前面的位置。最常见的就是匹配开始和结束位置。先来看一个开始位置的匹配,这里使用 /^ex/igm 来匹配多行中以ex 开头的行:使用/e$/igm来匹配以 e 结尾的行:可以使用 \w+$ 来匹配每一行的最后一个单词:需要注意,这里我们都使用 m 修饰符开启了多行模式。使用 /(?=the)/ig 来匹配字符串中the前的面的位置:我们可以使用\b来匹配单词的边界,匹配的结果如下:这可能比较难理解,我们可以使用以下正则表达式来匹配完整的单词:\b\w+\b,匹配结果如下:捕获组正则表达式中的“捕获组”是指使用括号 () 将子模式括起来,以便于在搜索时同时匹配多个项或将匹配的内容单独提取出来。组可以根据需要进行嵌套,形成复杂的匹配模式。使用捕获组,可以直接在正则表达式 /(Testing|tests) 123/ig 中匹配到 "Testing 123" 和 "Tests 123",而不需要重复写 "123" 的匹配项。正则表达式中的两种常见组类型:(...):捕获组,用于匹配任意三个字符。(?:...):非捕获组,也是用于匹配任意三个字符,但不进行捕获。可以使用以下 JavaScript 将文本替换为Testing 234和tests 234:const regex = /(Testing|tests) 123/ig; let str = ` Testing 123 Tests 123 `; str = str.replace(regex, '$1 234'); console.log(str); // Testing 234 // Tests 234 被括号包围的子模式称为“捕获组”,捕获组可以从匹配的字符串中提取出指定的部分并单独使用。这里我们使用 $1 来引用第一个捕获组 (Testing|tests)。也可以匹配多个组,比如同时匹配 (Testing|tests) 和 (123)。const regex = /(Testing|tests) (123)/ig; let str = ` Testing 123 Tests 123 `; str = str.replace(regex, '$1 #$2'); console.log(str); // Testing #123 // Tests #123" 这只适用于捕获组。如果把上面的正则表达式变成这样:/(?:Testing|tests) (123)/ig; 那么只有一个被捕获的组:(123),与之前相同的代码将输出不同的结果:const regex = /(?:Testing|tests) (123)/ig; let str = ` Testing 123 Tests 123 `; str = str.replace(regex, '$1'); console.log(str); // 123 // 123 修改后的正则表达式只有一个捕获组 (123)。因为 (?: ) 的语法用于创建非捕获组,所以它不会将其内容作为一个捕获组来使用。命名捕获组虽然捕获组非常有用,但是当有很多捕获组时很容易让人困惑。$3 和 $5 这些名字并不是一目了然的。为了解决这个问题,正则表达式引入了“命名捕获组”的概念。例如,(?<name>...) 就是一个命名捕获组,名为 "name",用于匹配任意三个字符。可以像这样在正则表达式中使用它来创建一个名为 "num" 的组,用于匹配三个数字:/Testing (?<num>\d{3})/ 然后,可以在替换操作中像这样使用它:const regex = /Testing (?<num>\d{3})/ let str = "Testing 123"; str = str.replace(regex, "Hello $<num>") console.log(str); // "Hello 123" 命名反向引用有时候需要在查询字符串中引用一个命名捕获组,这就是“反向引用”的用武之地。假设有一个字符串,其中包含多个单词,我们想要找到所有出现两次或以上的单词。可以使用具名捕获组和命名反向引用来实现。const regex = /\b(?<word>\w+)\b(?=.*?\b\k<word>\b)/g; const str = 'I like to eat pizza, but I do not like to eat sushi.'; const result = str.match(regex); console.log(result); // like 这里使用了具名捕获组 (?<word>\w+)来匹配单词,并将其命名为 "word"。然后使用命名反向引用 (?=.*?\b\k<word>\b) 来查找文本中是否存在具有相同内容的单词。前瞻组和后顾组前瞻组(Lookahead)和后顾组(Lookbehind)是正则表达式中非常有用的工具,它们用于在匹配过程中进行条件约束,而不会实际匹配这些约束的内容。它们使得我们可以更精确地指定匹配模式。前瞻组:正向前瞻((?=...)):用于查找在某个位置后面存在的内容。例如,A(?=B) 可以匹配 "A",但只有在后面跟着 "B" 时才进行匹配。负向前瞻((?!...)):用于查找在某个位置后面不存在的内容。例如,A(?!B) 可以匹配 "A",但只有在后面不跟着 "B" 时才进行匹配。后顾组:正向后顾((?<=...)):用于查找在某个位置前面存在的内容。例如,(?<=A)B 可以匹配 "B",但只有在其前面跟着 "A" 时才进行匹配。负向后顾((?<!...)):用于查找在某个位置前面不存在的内容。例如,(?<!A)B 可以匹配 "B",但只有在其前面不跟着 "A" 时才进行匹配。这些前瞻组和后顾组可以用于各种场景,例如:在匹配邮箱地址时,使用正向前瞻来确保地址的结尾是以特定的域名结尾。在匹配密码时,使用正向前瞻来确保密码满足特定的复杂度要求。在提取文本中的日期时,使用正向后顾来确保日期的前面有特定的前缀。例如,使用负向前瞻可以匹配 BC,但不会匹配 BA。/B(?!A)/ 我们甚至可以将负向前瞻组合使用,并使用 ^ 和 $ 这些元字符来尝试匹配完整的字符串。例如,以下的正则表达式将匹配任何不以 "Test" 开头的字符串:/^(?!Test).*$/gm 这个正则表达式可以匹配 Hello 和 Other,但无法匹配 Testing 123 和 Tests 123。同样,可以将其切换为正向前瞻,以强制字符串必须以“Test”开头:/^(?=Test).*$/gm 三、字符串方法在 JavaScript 内置了 6 个常用的方法是支持正则表达式的,下面来分别看看这些方法。search()search() 方法用于检索字符串中指定的子字符串,或检索与正则表达式相匹配的子字符串,并返回子串的起始位置。如果没有找到任何匹配的子串,则返回 -1。const regex1 = /a/ig; const regex2 = /p/ig; const regex3 = /m/ig; const str = "Action speak louder than words"; console.log(str.search(regex1)); // 输出结果:0 console.log(str.search(regex2)); // 输出结果:8 console.log(str.search(regex3)); // 输出结果:-1 可以看到,search() 方法只会返回匹配到的第一个字符的索引值,当没有匹配到相应的值时,就会返回-1。match()match() 方法可在字符串内检索指定的值,或找到一个或多个正则表达式的匹配。如果没有找到任何匹配的文本, match() 将返回 null。否则,它将返回一个数组,其中存放了与它找到的匹配文本有关的信息。const regex1 = /a/ig; const regex2 = /a/i; const regex3 = /m/ig; const str = "Action speak louder than words"; console.log(str.match(regex1)); // 输出结果:['A', 'a', 'a'] console.log(str.match(regex2)); // 输出结果:['A', index: 0, input: 'Action speak louder than words', groups: undefined] console.log(str.match(regex3)); // 输出结果:null 可以看到,当没有 g 修饰符时,就只能在字符串中执行一次匹配,如果想要匹配所有符合条件的值,就需要添加 g 修饰符。matchAll()matchAll() 方法返回一个包含所有匹配正则表达式的结果及分组捕获组的迭代器。因为返回的是遍历器,所以通常使用for...of循环取出。for (const match of 'abcabc'.matchAll(/a/g)) { console.log(match) } //["a", index: 0, input: "abcabc", groups: undefined] //["a", index: 3, input: "abcabc", groups: undefined] 需要注意,该方法的第一个参数是一个正则表达式对象,如果传的参数不是一个正则表达式对象,则会隐式地使用 new RegExp(obj) 将其转换为一个 RegExp 。另外,RegExp必须是设置了全局模式g的形式,否则会抛出异常 TypeError。replace()replace() 用于在字符串中用一些字符串替换另一些字符串,或替换一个与正则表达式匹配的子串。const regex = /A/g; const str = "Action speak louder than words"; console.log(str.replace(regex, 'a')); // 输出结果:action speak louder than words 可以看到,第一个参数中的正则表达式匹配到了字符串的第一个大写的 A,并将其替换为了第二个参数中的小写的 a。replaceAll()replaceAll() 方法用于在字符串中用一些字符替换另一些字符,或替换一个与正则表达式匹配的子串,该函数会替换所有匹配到的子字符串。const regex = /a/g; const str = "Action speak louder than words"; console.log(str.replaceAll(regex, 'A')); // 输出结果:Action speAk louder thAn words 需要注意,当使用一个 regex 时,您必须设置全局("g")标志, 否则,它将引发 TypeError:"必须使用全局 RegExp 调用 replaceAll"。split()split() 方法用于把一个字符串分割成字符串数组。其第一个参数是一个字符串或正则表达式,从该参数指定的地方分割字符串。const regex = / /gi; const str = "Action speak louder than words"; console.log(str.split(regex)); // 输出结果:['Action', 'speak', 'louder', 'than', 'words'] 这里的 regex 用来匹配空字符串,所以最终在字符串的每个空格处将字符串拆成了数组。四、应用场景上面介绍了正则表达式的用法,下面就来看看正则表达式的实际应用场景。数据验证数据验证应该是正则表达式最常见的场景了,经常用于用户的输入是否符合所需的条件。数据验证可确保输入或导入的数据准确、一致,并符合预定义的规则。验证手机号:const phoneNumber = "13712345678"; const regex = /^1[3-9]\d{9}$/; console.log("手机号格式正确:", regex.test(phoneNumber)); 验证邮箱:const email = "example@example.com"; const regex = /^[^\s@]+@[^\s@]+\.[^\s@]+$/; console.log("电子邮件格式正确:", regex.test(email)); 验证密码(要求:至少包含一个数字,一个字母,一个特殊字符,长度在8~18之间):const password = "Abcdef.123"; const regex = /^(?=.*\d)(?=.*[a-zA-Z])(?=.*[\W_]).{8,18}$/; console.log("密码格式正确:", regex.test(password)) 验证输入内容不能包含 emoji 表情:function hasEmoji(str) { const emojiRegex = /[\uD800-\uDFFF]|[\u2600-\u27FF]|[\u1F000-\u1F9FF]/g; return emojiRegex.test(str); } // 测试样例 const text1 = 'Hello, world!'; const text2 = '你好,🌍!'; console.log(hasEmoji(text1)); // false console.log(hasEmoji(text2)); // true 搜索和替换搜索和替换是正则表达式的很常见的用例。它允许查找文本中的特定模式并将其替换为所需的内容。笔者之前做个一个需求:获取 HTML 字符串中所有图片,也就是获取所有 img 标签的 src 属性值,这个需求属于数据提取,第三部分会讲到;将获取到的图片转灰度图,转灰度成功的图片的名称会加一个-gray后缀,将这个图片替换 HTML 原来的图片。也就将转换成功的图片的src地址加-gray后缀。灰度图替换:const grayImgReplace = (html: string, imgUrl: string) => { const regex = /(https?:\/\/[^\s"']+\.[^\s"']+(?<!-gray))\.(jpg|jpeg|png)/; const match = regex.exec(html); if (match) { return html.replace(match[0], `${imgUrl}`); } return html; }; 注意:这里仅替换一张图,若需要替换多张,每个图片都执行该方法即可。另一个例子就是在 IDE 中进行正则表达式搜索和替换操作。比如,在 VS Code 中,只需在搜索栏中点击搜索栏左侧的正则表达式按钮(.*)或按下快捷键 Alt + R,就可以激活正则表达式搜索模式。比如,有一个动态接口路径:/app/api/:modal/list,想要看看哪些地方调用了这个接口。这个路径中间的 modal 是动态的,没办法直接通过字符串进行搜索,怎么办呢?可以借助正则表达式轻松实现:\/app\/api\/([^\/]+)\/list 不管 modal 是什么,都可以轻松搜索到:除此之外,还可以通过搜索替换轻松实现数据的格式化。例如,将数字转换为货币格式:const formatMoney = (money) => { return money.replace(new RegExp(`(?!^)(?=(\\d{3})+${money.includes('.') ? '\\.' : '$'})`, 'g'), ',') } formatMoney('123456789') // '123,456,789' formatMoney('123456789.123') // '123,456,789.123' formatMoney('123') // '123' 数据提取数据提取是正则表达式的另一个常见用例。正则表达式使我们能够根据定义的模式从较大的文本中有效地提取特定信息。上面提到了从 HTML 字符串中获取所有图片 URL 的需求,下面来实现一下:const getImgs = (domContent) => { const imgs = []; const imgPattern = /<img[^>]+src=['"]((?!.*\.svg).+?)['"]/g; let match = null; while ((match = imgPattern.exec(domContent)) !== null) { imgs.push(match[1]); } return imgs; }; 再比如,获取所有 a 标签链接,也就是获取 href 属性值:const html = '<a href="https://www.example.com">Link 1</a> <a href="https://www.google.com">Link 2</a>'; // 使用正则表达式提取 <a> 标签链接 const linkRegex = /<a\s+(?:[^>]*?\s+)?href=(["'])(.*?)\1/g; const links = []; let match; while ((match = linkRegex.exec(html)) !== null) { const link = match[2]; links.push(link); } console.log(links); 输出结果如下:[ 'https://www.example.com', 'https://www.google.com' ] 再比如,提取 URL 中的域名:const url = 'https://www.example.com/path/to/page?param1=value1¶m2=value2#section'; const domainRegex = /https?:\/\/([\w.-]+)/; const match = url.match(domainRegex); const domain = match && match[1]; console.log(domain); // www.example.com 数据清洗通过适当使用正则表达式,可以轻松地从文本数据中查找、匹配和替换特定的模式和字符,从而对数据进行清理和预处理。以下是一些常见的数据清洗任务,可以使用正则表达式来完成:移除多余空格:使用正则表达式将连续的多个空格或制表符替换为单个空格,或者完全移除所有空格。格式化日期:使用正则表达式解析和提取日期字符串,并将其格式化为指定的格式或日期对象。清除特殊字符:使用正则表达式从文本数据中移除不需要的特殊字符和标点符号,例如 emoji 表情符号、HTML 标签、URL 等。提取信息:使用正则表达式从文本数据中提取特定的信息,例如电话号码、邮件地址、IP 地址等。替换错误或不一致的数据:使用正则表达式查找和替换文本数据中的错误拼写、大小写、颠倒顺序等问题,使得数据更加一致和规范化。比如,删除字符串中的标签和 emoji 表情:const text = 'Hello, <b>world</b>! 🌍'; const cleanText = text.replace(/<\/?[^>]+(>|$)/g, '').replace(/[\uD800-\uDBFF][\uDC00-\uDFFF]/g, ''); console.log(cleanText); // Hello, world! 这里使用了两个正则表达式替换操作:/<\/?[^>]+(>|$)/g:这个正则表达式用于匹配并移除 HTML 标签。它会匹配尖括号内的任何内容,并将其替换为空字符串。/[\uD800-\uDBFF][\uDC00-\uDFFF]/g:这个正则表达式用于匹配并移除 emoji 表情符号。由于 emoji 符号采用 Unicode 编码的多个字符表示,我们使用这个正则表达式匹配并移除这些字符。五、实用工具Regex101Regex101 是学习正则表达式最有效的工具网站之一,本文的示例使用的就是这个工具。在REGULAR EXPRESSION栏中可以输入正则表达式,可以在输入框右侧选择需要的修饰符,在下面的TEST STRING栏中输入要测试的字符串,即可显示出匹配到的结果。在右侧的EXPLANATION区域会显示出对输入的正则表达式的详细解释。右下角的 QUICK REFERENCE 栏会显示正则表达式速查表。Regex101 还支持在上面练习编写正则表达式:可以在上面搜索一些正则表达式的库:除此之外,我们还可以使用 RegexDebugger 来跟踪匹配的过程。更多功能可以在Regex101 上进行探索。官网: https://regex101.com/RegExrRegExr 是一个基于 JavaScript 开发的在线工具,用来创建、测试和学习正则表达式。它是一个开源的工具,具有以下特性:输入时,结果会实时更新;支持 JavaScript 和 PHP/PCRE RegEx;将匹配项或表达式移至详细信息;保存并与他人共享表达式;使用工具探索结果;浏览参考以获取帮助和示例;在编辑器中使用 cmd-Z/Y 撤消和重做。官网: https://regexr.com/Regex PalRegexpal 是一个基于 Javascript 的在线正则表达式验证工具。它的页面非常简洁,只有两个输入框,上面的输入框中可以输入正则表达式(匹配规则),下面的输入框可以输入待匹配的数据。此外,根据具体要求,还可以设置忽略大小写、多行匹配等参数。官网: https://www.regexpal.com/Regex-VisRegex-Vis 是一个辅助学习、编写和验证正则的工具。它不仅能对正则进行可视化展示,而且提供可视编辑正则的能力。在输入一个正则表达式后,会生成它的可视化图形。然后可以点选或框选图形中的单个或多个节点,再在右侧操作面板对其进行操作,具体操作取决于节点的类型,比如在其右侧插入空节点、为节点编组、为节点增加量词等。官网: https://regex-vis.com/Regex previewerRegex previewer 是一个 VScode 插件,在插件市场搜索名称即可安装。当我们在编写正则表达式时,可以直接使用快捷键 Ctrl+Alt+M (windows)或者 ⌥+⌘+M(Mac)在编辑器右侧启动一个标签页,我们可以在这个标签页写一写测试用例,用来测试我们写的正则表达式,写完字符串用例之后,点击我们编写的正则表达式上方的 Test Regex...即可,这样右侧匹配到字符就会高亮显示了,如下图:
2023年10月13日
57 阅读
0 评论
0 点赞
2023-08-30
正则表达式速查手册
正则表达式速查手册
2023年08月30日
10 阅读
0 评论
0 点赞
2023-08-07
PERL(PCRE)和POSIX模式正则区别
PERL(PCRE)和POSIX模式正则区别POSIX 是 UNIX 遵循的标准, UNIX 的命令如 grep、sed 能用的正则是 POSIX。PERL 正则在 POSIX 上做了扩展,实现了很多方便的功能。举个匹配数字的例子,Perl 用 \d,POSIX 用 [0-9](POSIX 老版本,现在也有 \d 了)。POSIX 里面还有“类”的概念,比如 [:digit:] 用来匹配数字, Perl 原先没有,后来支持 POSIX,也能用了。再举个例子,Perl 里面的正则 a.b 和 a.?b,匹配的对象是不一样的。a.b 实现最长匹配,a.?b 实现最短匹配,用这两个表达式匹配字符串"a 1b 2b",第一个的匹配结果是 "a 1b 2b",第二个的匹配结果是 "a 1b"。PHP同时使用两套正则表达式规则,一套是由电气和电子工程师协会(IEEE)制定的POSIX Extended 1003.2兼容正则(事实上PHP对此标准的支持并不完善),另一套来自PCRE(Perl Compatible Regular Expression)库提供PERL兼容正则,这是个开放源代码的软件,作者为 Philip Hazel。使用POSIX兼容规则的函数有:ereg_replace()ereg()eregi()eregi_replace()split()spliti()sql_regcase()mb_ereg_match()mb_ereg_replace()mb_ereg_search_getpos()mb_ereg_search_getregs()mb_ereg_search_init()mb_ereg_search_pos()mb_ereg_search_regs()mb_ereg_search_setpos()mb_ereg_search()mb_ereg()mb_eregi_replace()mb_eregi()mb_regex_encoding()mb_regex_set_options()mb_split()使用PERL兼容规则的函数有:preg_grep()preg_replace_callback()preg_match_all()preg_match()preg_quote()preg_split()preg_replace()定界符:POSIX兼容正则没有定界符,函数的相应参数会被认为是正则。PERL兼容正则可以使用任何不是字母、数字或反斜线(\)的字符作为定界符,如果作为定界符的字符必须被用在表达式本身中,则需要用反斜线转义。也可以使用(),{},[] 和 <> 作为定界符修正符:POSIX兼容正则没有修正符。PERL兼容正则中可能使用的修正符(修正符中的空格和换行被忽略,其它字符会导致错误):i (PCRE_CASELESS):匹配时忽略大小写。m(PCRE_MULTILINE):当设定了此修正符,行起始(^)和行结束($)除了匹配整个字符串开头和结束外,还分别匹配其中的换行符(\n)的之后和之前。s(PCRE_DOTALL):如果设定了此修正符,模式中的圆点元字符(.)匹配所有的字符,包括换行符。没有此设定的话,则不包括换行符。x(PCRE_EXTENDED):如果设定了此修正符,模式中的空白字符除了被转义的或在字符类中的以外完全被忽略。e:如果设定了此修正符,preg_replace() 在替换字符串中对逆向引用作正常的替换,将其作为 PHP 代码求值,并用其结果来替换所搜索的字符串。 只有 preg_replace() 使用此修正符,其它 PCRE 函数将忽略之。A(PCRE_ANCHORED):如果设定了此修正符,模式被强制为“anchored”,即强制仅从目标字符串的开头开始匹配。D(PCRE_DOLLAR_ENDONLY):如果设定了此修正符,模式中的行结束($)仅匹配目标字符串的结尾。没有此选项时,如果最后一个字符是换行符的话,也会被匹配在里面。如果设定了 m 修正符则忽略此选项。S:当一个模式将被使用若干次时,为加速匹配起见值得先对其进行分析。如果设定了此修正符则会进行额外的分析。目前,分析一个模式仅对没有单一固定起始字符的 non-anchored 模式有用。U(PCRE_UNGREEDY):使“?”的默认匹配成为贪婪状态的。X(PCRE_EXTRA):模式中的任何反斜线后面跟上一个没有特殊意义的字母导致一个错误,从而保留此组合以备将来扩充。默认情况下,一个反斜线后面跟一个没有特殊意义的字母被当成该字母本身。u(PCRE_UTF8):模式字符串被当成UTF-8。逻辑区隔:POSIX兼容正则和PERL兼容正则的逻辑区隔符号作用和使用方法完全一致:[]:包含任选一操作的相关信息。{}:包含匹配次数的相关信息。():包含一个逻辑区间的相关信息,可被用来进行引用操作。|:表示“或”,[ab]和a|b是等价的。元字符与“[]”相关:有两组不同的元字符:一种是模式中除了方括号内都能被识别的,还有一种是在方括号“[]”内被识别的。POSIX兼容正则和PERL兼容正则“[]之外”“一致”的元字符:\ 有数种用途的通用转义符^ 匹配字符串的开头$ 匹配字符串的结尾? 匹配0或者1匹配 0 个或多个前面指定类型的字符匹配 1 个或多个前面指定类型的字符POSIX兼容正则和PERL兼容正则“[]之外”“不一致”的元字符:. PERL兼容正则匹配除了换行符外的任意一个字符. POSIX兼容正则匹配任意一个字符POSIX兼容正则和PERL兼容正则“[]之内”“一致”的元字符:\ 有数种用途的通用转义符^ 取反字符,但仅当其为第一个字符时有效指定字符ASCII范围,仔细研究ASCII码,你会发现[W-c]等价于[WXYZ\^_`abc]POSIX兼容正则和PERL兼容正则“[]之内”“不一致”的元字符:POSIX兼容正则中[a-c-e]的指定会抛出错误。PERL兼容正则中[a-c-e]的指定等价于[a-e]。匹配次数与“{}”相关:POSIX兼容正则和PERL兼容正则在匹配次数方面完全一致:{2}:表示匹配前面的字符2次{2,}:表示匹配前面的字符2次或多次,默认都是贪婪(尽可能多)的匹配{2,4}:表示匹配前面的字符2次或4次逻辑区间与“()”相关:使用()包含起来的区域是一个逻辑区间,逻辑区间的主要作用是体现出一些字符出现的逻辑次序,另一个用处就是可以用来引用(可以将此区间内的值引用给一个变量)。后一个作用比较奇特:<?php$str = "http://www.163.com/";// POSIX兼容正则:echo ereg_replace("(.+)","\1",$str);// PERL兼容正则:echo preg_replace("/(.+)/","
2023年08月07日
15 阅读
0 评论
0 点赞
2023-08-07
php 的正则表达式完全手册
php 的正则表达式完全手册前言正则表达式是烦琐的,但是强大的,学会之后的应用会让你除了提高效率外,会给你带来绝对的成就感。只要认真去阅读这些资料,加上应用的时候进行一定的参考,掌握正则表达式不是问题。索引1._引子2._正则表达式的历史3._正则表达式定义3.1_普通字符3.2_非打印字符3.3_特殊字符3.4_限定符3.5_定位符3.6_选择3.7_后向引用4._各种操作符的运算优先级5._全部符号解释6._部分例子7._正则表达式匹配规则7.1_基本模式匹配7.2_字符簇7.3_确定重复出现引子目前,正则表达式已经在很多软件中得到广泛的应用,包括*nix(Linux, Unix 等) HP 等操作系统,,PHP,C#,Java 等开发环境,以及很多的应用软件中,都可以看到正则表达式的影子。正则表达式的使用,可以通过简单的办法来实现强大的功能。为了简单有效而又不失强大,造成了正则表达式代码的难度较大,学习起来也不是很容易,所以需要付出一些努力才行,入门之后参照一定的参考,使用起来还是比较简单有效的。例子: ^.+@.+\..+$这样的代码曾经多次把我自己给吓退过。可能很多人也是被这样的代码给吓跑的吧。继续阅读本文将让你也可以自由应用这样的代码。注意:这里的第 7 部分跟前面的内容看起来似乎有些重复,目的是把前面表格里的部分重新描述了一次,目的是让这些内容更容易理解。正则表达式的历史正则表达式的“祖先”可以一直上溯至对人类神经系统如何工作的早期研究。Warren McCulloch 和Walter Pitts 这两位神经生理学家研究出一种数学方式来描述这些神经网络。年, 一位叫 Stephen Kleene 的数学家在 McCulloch 和 Pitts 早期工作的基础上,发表了一篇标题为“神经网事件的表示法”的论文,引入了正则表达式的概念。正则表达式就是用来描述他称为“正则集的代数”的表达式,因此采用“正则表达式”这个术语。随后,发现可以将这一工作应用于使用 Ken Thompson 的计算搜索算法的一些早期研究, ThompsonKen是 Unix 的主要发明人。正则表达式的第一个实用应用程序就是 Unix 中的 qed 编辑器。如他们所说,剩下的就是众所周知的历史了。从那时起直至现在正则表达式都是基于文本的编辑器和搜索工具中的一个重要部分。正则表达式定义正则表达式(regular expression)描述了一种字符串匹配的模式,可以用来检查一个串是否含有某种子串、将匹配的子串做替换或者从某个串中取出符合某个条件的子串等。列目录时,dir .txt 或 ls .txt 中的.txt 就不是一个正则表达式,因为这里与正则式的*的含义是不同的。正则表达式是由普通字符(例如字符 a 到 z)以及特殊字符(称为元字符)组成的文字模式。正则表达式作为一个模板,将某个字符模式与所搜索的字符串进行匹配。3.1 普通字符由所有那些未显式指定为元字符的打印和非打印字符组成。这包括所有的大写和小写字母字符,所有数字,所有标点符号以及一些符号。3.2 非打印字符字符 含义\cx 匹配由 x 指明的控制字符。例如, \cM 匹配一个 Control-M 或回车符。 的值必须为 A-Z 或 a-z 之x一。否则,将 c 视为一个原义的 'c' 字符。\f 匹配一个换页符。等价于 \x0c 和 \cL。\n 匹配一个换行符。等价于 \x0a 和 \cJ。\r 匹配一个回车符。等价于 \x0d 和 \cM。\s 匹配任何空白字符,包括空格、制表符、换页符等等。等价于 [ \f\n\r\t\v]。\S 匹配任何非空白字符。等价于 1。\t 匹配一个制表符。等价于 \x09 和 \cI。\v 匹配一个垂直制表符。等价于 \x0b 和 \cK。3.3 特殊字符所谓特殊字符,就是一些有特殊含义的字符,如上面说的".txt"中的,简单的说就是表示任何字符串的意思。如果要查找文件名中有的文件,则需要对进行转义,即在其前加一个\。ls *.txt。正则表达式有以下特殊字符。特别字符 说明$ 匹配输入字符串的结尾位置。如果设置了 RegExp 对象的 Multiline 属性, $ 也匹配 '\n' 或 '\r'。则要匹配 $ 字符本身,请使用 \$。( ) 标记一个子表达式的开始和结束位置。子表达式可以获取供以后使用。要匹配这些字符,请使用 ( 和)。匹配前面的子表达式零次或多次。要匹配 * 字符,请使用 *。匹配前面的子表达式一次或多次。要匹配 + 字符,请使用 +。. 匹配除换行符 \n 之外的任何单字符。要匹配 .,请使用 \。[ 标记一个中括号表达式的开始。要匹配 [,请使用 [。? 匹配前面的子表达式零次或一次,或指明一个非贪婪限定符。要匹配 ? 字符,请使用 ?。\ 将下一个字符标记为或特殊字符、或原义字符、或向后引用、或八进制转义符。例如, 'n' 匹配字符 'n'。'\n' 匹配换行符。序列 '\' 匹配 "\",而 '(' 则匹配 "("。^ 匹配输入字符串的开始位置,除非在方括号表达式中使用,此时它表示不接受该字符集合。要匹配 ^ 字符本身,请使用 ^。{ 标记限定符表达式的开始。要匹配 {,请使用 {。| 指明两项之间的一个选择。要匹配 |,请使用 |。构造正则表达式的方法和创建数学表达式的方法一样。也就是用多种元字符与操作符将小的表达式结合在一起来创建更大的表达式。正则表达式的组件可以是单个的字符、字符集合、字符范围、字符间的选择或者所有这些组件的任意组合。3.4 限定符限定符用来指定正则表达式的一个给定组件必须要出现多少次才能满足匹配。有*或+或?或{n}或{n,}或{n,m}共 6 种。*、+和?限定符都是贪婪的,因为它们会尽可能多的匹配文字,只有在它们的后面加上一个?就可以实现非贪婪或最小匹配。正则表达式的限定符有:字符 描述匹配前面的子表达式零次或多次。例如,zo 能匹配 "z" 以及 "zoo"。 等价于{0,}。匹配前面的子表达式一次或多次。例如,'zo+' 能匹配 "zo" 以及 "zoo",但不能匹配 "z"。+ 等价于{1,}。? 匹配前面的子表达式零次或一次。例如,"do(es)?" 可以匹配 "do" 或 "does" 中的"do" 。? 等价于{0,1}。{n} n 是一个非负整数。匹配确定的 n 次。例如,'o{2}' 不能匹配 "Bob" 中的 'o',但是能匹配 "food"中的两个 o。{n,} n 是一个非负整数。至少匹配 n 次。例如,'o{2,}' 不能匹配 "Bob" 中的 'o',但能匹配 "foooood"中的所有 o。'o{1,}' 等价于 'o+'。'o{0,}' 则等价于 'o*'。{n,m} m 和 n 均为非负整数,其中 n <= m。最少匹配 n 次且最多匹配 m 次。例如,"o{1,3}" 将匹配"fooooood" 中的前三个 o。'o{0,1}' 等价于 'o?'。请注意在逗号和两个数之间不能有空格。3.5 定位符用来描述字符串或单词的边界,^和$分别指字符串的开始与结束,\b 描述单词的前或后边界,\B 表示非单词边界。不能对定位符使用限定符。3.6 选择用圆括号将所有选择项括起来,相邻的选择项之间用|分隔。但用圆括号会有一个副作用,是相关的匹配会被缓存,此时可用?:放在第一个选项前来消除这种副作用。其中?:是非捕获元之一,还有两个非捕获元是?=和?!,这两个还有更多的含义,前者为正向预查,在任何开始匹配圆括号内的正则表达式模式的位置来匹配搜索字符串,后者为负向预查,在任何开始不匹配该正则表达式模式的位置来匹配搜索字符串。3.7 后向引用对一个正则表达式模式或部分模式两边添加圆括号将导致相关匹配存储到一个临时缓冲区中,所捕获的每个子匹配都按照在正则表达式模式中从左至右所遇到的内容存储。存储子匹配的缓冲区编号从 1 开始,连续编号直至最大 99 个子表达式。每个缓冲区都可以使用 '\n' 访问,其中 n 为一个标识特定缓冲区的一位或两位十进制数。可以使用非捕获元字符 '?:', '?=', or '?!' 来忽略对相关匹配的保存。各种操作符的运算优先级相同优先级的从左到右进行运算,不同优先级的运算先高后低。各种操作符的优先级从高到低如下:操作符 描述\ 转义符(), (?:), (?=), [] 圆括号和方括号*, +, ?, {n}, {n,}, {n,m} 限定符^, $, \anymetacharacter 位置和顺序| “或”操作全部符号解释字符 描述\ 将下一个字符标记为一个特殊字符、或一个原义字符、或一个 向后引用、或一个八进制转义符。例如,'n' 匹配字符 "n"。'\n' 匹配一个换行符。序列 '\' 匹配 "\" 而 "(" 则匹配 "("。^ 匹配输入字符串的开始位置。如果设置了 RegExp 对象的 Multiline 属性,^ 也匹配 '\n' 或 '\r' 之后的位置。$ 匹配输入字符串的结束位置。如果设置了 RegExp 对象的 Multiline 属性,$ 也匹配 '\n' 或 '\r' 之前的位置。匹配前面的子表达式零次或多次。例如,zo 能匹配 "z" 以及 "zoo"。 等价于{0,}。匹配前面的子表达式一次或多次。例如,'zo+' 能匹配 "zo" 以及 "zoo",但不能匹配 "z"。+ 等价于{1,}。? 匹配前面的子表达式零次或一次。例如,"do(es)?" 可以匹配 "do" 或 "does" 中的"do" 。? 等价于{0,1}。{n} n 是一个非负整数。匹配确定的 n 次。例如,'o{2}' 不能匹配 "Bob" 中的 'o',但是能匹配 "food"中的两个 o。{n,} n 是一个非负整数。至少匹配 n 次。例如,'o{2,}' 不能匹配 "Bob" 中的 'o',但能匹配 "foooood"中的所有 o。'o{1,}' 等价于 'o+'。'o{0,}' 则等价于 'o*'。{n,m} m 和 n 均为非负整数,其中 n <= m。最少匹配 n 次且最多匹配 m 次。例如,"o{1,3}" 将匹配"fooooood" 中的前三个 o。'o{0,1}' 等价于 'o?'。请注意在逗号和两个数之间不能有空格。? 当该字符紧跟在任何一个其他限制符 (*, +, ?, {n}, {n,}, {n,m}) 后面时,匹配模式是非贪婪的。非贪婪模式尽可能少的匹配所搜索的字符串,而默认的贪婪模式则尽可能多的匹配所搜索的字符串。例如,对于字符串 "oooo",'o+?' 将匹配单个 "o",而 'o+' 将匹配所有 'o'。. 匹配除 "\n" 之外的任何单个字符。要匹配包括 '\n' 在内的任何字符,请使用象 '[.\n]' 的模式。(pattern) 匹配 pattern 并获取这一匹配。所获取的匹配可以从产生的 Matches 集合得到,在 VBScript中使用 SubMatches 集合,在 JScript 中则使用 $0„$9 属性。要匹配圆括号字符,请使用 '(' 或')'。(?:pattern) 匹配 pattern 但不获取匹配结果,也就是说这是一个非获取匹配,不进行存储供以后使用。这在使用 "或" 字符 (|) 来组合一个模式的各个部分是很有用。例如, 'industr(?:y|ies) 就是一个比'industry|industries' 更简略的表达式。(?=pattern) 正向预查,在任何匹配 pattern 的字符串开始处匹配查找字符串。这是一个非获取匹配,也就是说,该匹配不需要获取供以后使用。例如,'Windows (?=95|98|NT|2000)' 能匹配 "Windows 2000" 中的 "Windows" ,但不能匹配 "Windows 3.1" 中的 "Windows"。预查不消耗字符,也就是说,在一个匹配发生后,在最后一次匹配之后立即开始下一次匹配的搜索,而不是从包含预查的字符之后开始。(?!pattern) 负向预查,在任何不匹配 pattern 的字符串开始处匹配查找字符串。这是一个非获取匹配,也就是说,该匹配不需要获取供以后使用。例如'Windows (?!95|98|NT|2000)' 能匹配 "Windows 3.1" 中的 "Windows",但不能匹配 "Windows 2000" 中的 "Windows"。预查不消耗字符,也就是说,在一个匹配发生后,在最后一次匹配之后立即开始下一次匹配的搜索,而不是从包含预查的字符之后开始x|y 匹配 x 或 y。例如,'z|food' 能匹配 "z" 或 "food"。'(z|f)ood' 则匹配 "zood" 或 "food"。[xyz] 字符集合。匹配所包含的任意一个字符。例如, '[abc]' 可以匹配 "plain" 中的 'a'。2 负值字符集合。匹配未包含的任意字符。例如, '3' 可以匹配 "plain" 中的'p'。[a-z] 字符范围。匹配指定范围内的任意字符。例如,'[a-z]' 可以匹配 'a' 到 'z' 范围内的任意小写字母字符。4 负值字符范围。匹配任何不在指定范围内的任意字符。例如,'4' 可以匹配任何不在 'a' 到'z' 范围内的任意字符。\b 匹配一个单词边界,也就是指单词和空格间的位置。例如, 'er\b' 可以匹配"never" 中的 'er',但不能匹配 "verb" 中的 'er'。\B 匹配非单词边界。'er\B' 能匹配 "verb" 中的 'er',但不能匹配 "never" 中的 'er'。\cx 匹配由 x 指明的控制字符。例如, \cM 匹配一个 Control-M 或回车符。 的值必须为 A-Z 或 a-z 之x一。否则,将 c 视为一个原义的 'c' 字符。\d 匹配一个数字字符。等价于 [0-9]。\D 匹配一个非数字字符。等价于 5。\f 匹配一个换页符。等价于 \x0c 和 \cL。\n 匹配一个换行符。等价于 \x0a 和 \cJ。\r 匹配一个回车符。等价于 \x0d 和 \cM。\s 匹配任何空白字符,包括空格、制表符、换页符等等。等价于 [ \f\n\r\t\v]。\S 匹配任何非空白字符。等价于 6。\t 匹配一个制表符。等价于 \x09 和 \cI。\v 匹配一个垂直制表符。等价于 \x0b 和 \cK。\w 匹配包括下划线的任何单词字符。等价于'[A-Za-z0-9_]'。\W 匹配任何非单词字符。等价于 '7'。\xn 匹配 n,其中 n 为十六进制转义值。十六进制转义值必须为确定的两个数字长。例如,'\x41' 匹配 "A"。'\x041' 则等价于 '\x04' & "1"。正则表达式中可以使用 ASCII 编码。.\num 匹配 num,其中 num 是一个正整数。对所获取的匹配的引用。例如,'(.)\1' 匹配两个连续的相同字符。\n 标识一个八进制转义值或一个向后引用。如果 \n 之前至少 n 个获取的子表达式,则 n 为向后引用。否则,如果 n 为八进制数字 (0-7),则 n 为一个八进制转义值。\nm 标识一个八进制转义值或一个向后引用。如果 \nm 之前至少有 nm 个获得子表达式,则 nm 为向后引用。如果 \nm 之前至少有 n 个获取,则 n 为一个后跟文字 m 的向后引用。如果前面的条件都不满足,若 n 和 m 均为八进制数字 (0-7),则 \nm 将匹配八进制转义值 nm。\nml 如果 n 为八进制数字 (0-3),且 m 和 l 均为八进制数字 (0-7),则匹配八进制转义值 nml。\un 匹配 n,其中 n 是一个用四个十六进制数字表示的 Unicode 字符。例如, \u00A9 匹配版权符号(?)。部分例子正则表达式 说明/\b([a-z]+) \1\b/gi 一个单词连续出现的位置/(\w+)://(8+)(:\d)?(9)/ 将一个 URL 解析为协议、域、端口及相对路径/^(?:Chapter|Section) 1-9{0,1}$/ 定位章节的位置/[-a-z]/ A 至 z 共 26 个字母再加一个-号。/ter\b/ 可匹配 chapter,而不能 terminal/\Bapt/ 可匹配 chapter,而不能 aptitude/Windows(?=95 |98 |NT )/ 可匹配 Windows95 或 Windows98 或 WindowsNT,当找到一个匹配后,从 Windows后面开始进行下一次正则表达式匹配规则7.1 基本模式匹配一切从最基本的开始。模式,是正规表达式最基本的元素,它们是一组描述字符串特征的字符。模式可以很简单,由普通的字符串组成,也可以非常复杂,往往用特殊的字符表示一个范围内的字符、重复出现,或表示上下文。例如:^once这个模式包含一个特殊的字符^,表示该模式只匹配那些以 once 开头的字符串。例如该模式与字符串"once upon a time"匹配,与"There once was a man from NewYork"不匹配。正如如^符号表示开头一样,$符号用来匹配那些以给定模式结尾的字符串。bucket$这个模式与"Who kept all of this cash in a bucket"匹配,与"buckets"不匹配。字符^和$同时使用时,表示精确匹配(字符串与模式一样)。例如:^bucket$只匹配字符串"bucket"。如果一个模式不包括^和$,那么它与任何包含该模式的字符串匹配。例如:模式once与字符串There once was a man from NewYorkWho kept all of his cash in a bucket.是匹配的。在该模式中的字母(o-n-c-e)是字面的字符,也就是说,他们表示该字母本身,数字也是一样的。其他一些稍微复杂的字符,如标点符号和白字符(空格、制表符等),要用到转义序列。所有的转义序列都用反斜杠()打头。制表符的转义序列是:\t。所以如果我们要检测一个字符串是否以制表符开头,可以用这个模式:^\t类似的,用\n 表示“新行”,\r 表示回车。其他的特殊符号,可以用在前面加上反斜杠,如反斜杠本身用\表示,句号.用.表示,以此类推。7.2 字符簇在 INTERNET 的程序中,正规表达式通常用来验证用户的输入。当用户提交一个 FORM 以后,要判断输入的电话号码、地址、EMAIL 地址、信用卡号码等是否有效,用普通的基于字面的字符是不够的。所以要用一种更自由的描述我们要的模式的办法,它就是字符簇。要建立一个表示所有元音字符的字符簇,就把所有的元音字符放在一个方括号里:[AaEeIiOoUu]这个模式与任何元音字符匹配,但只能表示一个字符。用连字号可以表示一个字符的范围,如:[a-z] //匹配所有的小写字母[A-Z] //匹配所有的大写字母[a-zA-Z] //匹配所有的字母[0-9] //匹配所有的数字[0-9.-] //匹配所有的数字,句号和减号[ \f\r\t\n] //匹配所有的白字符同样的,这些也只表示一个字符,这是一个非常重要的。如果要匹配一个由一个小写字母和一位数字组成的字符串,比如"z2"、"t6"或"g7",但不是"ab2"、"r2d3" 或"b52"的话,用这个模式:^a-z$尽管[a-z]代表 26 个字母的范围,但在这里它只能与第一个字符是小写字母的字符串匹配。前面曾经提到^表示字符串的开头,但它还有另外一个含义。当在一组方括号里使用^是,它表示“非”或“排除”的意思,常常用来剔除某个字符。还用前面的例子,我们要求第一个字符不能是数字:^5[0-9]$这个模式与"&5"、"g7"及"-2"是匹配的,但与"12"、"66"是不匹配的。下面是几个排除特定字符的例子:4 //除了小写字母以外的所有字符10 //除了()(/)(^)之外的所有字符11 //除了双引号(")和单引号(')之外的所有字符特殊字符"." (点,句号)在正规表达式中用来表示除了“新行”之外的所有字符。所以模式"^.5$"与任何两个字符的、以数字 5 结尾和以其他非“新行”字符开头的字符串匹配。模式"."可以匹配任何字符串,除了空串和只包括一个“新行”的字符串。PHP 的正规表达式有一些内置的通用字符簇,列表如下:字符簇含义[[:alpha:]] 任何字母[[:digit:]] 任何数字[[:alnum:]] 任何字母和数字[[:space:]] 任何白字符[[:upper:]] 任何大写字母[[:lower:]] 任何小写字母[[:punct:]] 任何标点符号[[:xdigit:]] 任何 16 进制的数字,相当于[0-9a-fA-F]7.3 确定重复出现到现在为止,你已经知道如何去匹配一个字母或数字,但更多的情况下,可能要匹配一个单词或一组数字。一个单词有若干个字母组成,一组数字有若干个单数组成。跟在字符或字符簇后面的花括号({})用来确定前面的内容的重复出现的次数。字符簇 含义^[a-zA-Z_]$ 所有的字母和下划线^[[:alpha:]]{3}$ 所有的 3 个字母的单词^a$ 字母 a^a{4}$ aaaa^a{2,4}$ aa,aaa 或 aaaa^a{1,3}$ a,aa 或 aaa^a{2,}$ 包含多于两个 a 的字符串^a{2,} 如:aardvark 和 aaab,但 apple 不行a{2,} 如:baad 和 aaa,但 Nantucket 不行\t{2} 两个制表符.{2} 所有的两个字符这些例子描述了花括号的三种不同的用法。一个数字,{x}的意思是“前面的字符或字符簇只出现 x 次”;一个数字加逗号,{x,}的意思是“前面的内容出现 x 或更多的次数”;两个用逗号分隔的数字,{x,y}表示“前面的内容至少出现 x 次,但不超过 y 次”。我们可以把模式扩展到更多的单词或数字:^[a-zA-Z0-9_]{1,}$ //所有包含一个以上的字母、数字或下划线的字符串^[0-9]{1,}$ //所有的正数^-{0,1}[0-9]{1,}$ //所有的整数^-{0,1}[0-9]{0,}.{0,1}[0-9]{0,}$ //所有的小数最后一个例子不太好理解,是吗?这么看吧:与所有以一个可选的负号(-{0,1})开头(^)、跟着 0 个或更多的数字([0-9]{0,})、和一个可选的小数点(.{0,1})再跟上 0 个或多个数字([0-9]{0,}),并且没有其他任何东西($)。下面你将知道能够使用的更为简单的方法。特殊字符"?"与{0,1}是相等的,它们都代表着: 个或 1 个前面的内容” “前面的内容是可选的”“0或。所以刚才的例子可以简化为:^-?[0-9]{0,}.?[0-9]{0,}$特殊字符"*"与{0,}是相等的,它们都代表着“0 个或多个前面的内容”。最后,字符"+"与 {1,}是相等的,表示“1 个或多个前面的内容”,所以上面的 4 个例子可以写成:^[a-zA-Z0-9_]+$ //所有包含一个以上的字母、数字或下划线的字符串^[0-9]+$ //所有的正数^-?[0-9]+$ //所有的整数^-?[0-9].?[0-9]$ //所有的小数当然这并不能从技术上降低正规表达式的复杂性,但可以使它们更容易阅读。 \f\n\r\t\v ↩xyz ↩abc ↩a-z ↩0-9 ↩ \f\n\r\t\v ↩A-Za-z0-9_ ↩/: ↩# ↩\/^ ↩\"\' ↩
2023年08月07日
12 阅读
0 评论
0 点赞
1
2