正则表达式(一)

一、模式(Patterns)和修饰符(flags)

通过正则表达式,我们可以在文本中进行搜索和替换操作,也可以和字符串方法结合使用。

正则表达式

正则表达式(可叫作 "regexp",或 "reg")由 模式 和可选的 修饰符 组成。

语法:

javascript 复制代码
regexp = new RegExp("pattern", "flags");
regexp = /pattern/; // 没有修饰符
regexp = /pattern/gmi; // 带有修饰符 

斜线 /.../ 告诉 JavaScript 我们正在创建一个正则表达式。它的作用与字符串的引号作用相同。

注意:

这两种语法之间的主要区别在于,使用斜线 /.../ 的模式不允许插入表达式(如带有 ${...} 的字符串模板)。它是完全静态的。

从动态生成的字符串创建一个正则表达式时,使用new RegExp 例:

javascript 复制代码
let tag = prompt("What tag do you want to find?", "h2");
 // 如果在上方输入到 prompt 中的答案是 "h2",则与 /<h2>/ 相同
let regexp = new RegExp(`<${tag}>`);

1.修饰符

● i :使用此修饰符后,搜索时不区分大小写:A 和 a 之间没有区别

● g :使用此修饰符后,搜索时会寻找所有的匹配项 ------ 没有它,则仅返回第一个匹配项。

● m : 多行模式

● s :启用 "dotall" 模式,允许点 . 匹配换行符 \n)。

● u :开启完整的 Unicode 支持。该修饰符能够正确处理代理对。

● y :粘滞(Sticky)模式,在文本中的确切位置搜索

2.搜索:str.match()

str.match(regexp) 方法在字符串 str 中寻找 regexp 的所有匹配项。

正则表达式具有修饰符 g

javascript 复制代码
//返回一个由所有匹配项所构成的数组:
let str = "We will, we will rock you";
alert( str.match(/we/gi) ); // We,we(由两个匹配的子字符串构成的数组)
console.log(str.match(/we/gi) )

请注意,We 和 we 都被找到了,因为修饰符 i 使得正则表达式在进行搜索时不区分大小写。

没有修饰符 g

如果没有这样的修饰符,它则会以数组形式返回第一个匹配项,索引 0 处保存着完整的匹配项,返回的结果的属性中还有一些其他详细信息:

javascript 复制代码
let str = "We will, we will rock you";

let result = str.match(/we/i); // 没有修饰符 g
console.log( result ); 
console.log( result[0] );     // We(第一个匹配项)
console.log( result.length ); // 1

// 详细信息:
console.log( result.index );  // 0(匹配项的位置)
console.log( result.input );  // We will, we will rock you(源字符串)

如果正则表达式中有一部分内容被包在括号里,那么返回的数组可能会有 0 以外的索引。

没有匹配项

如果没有匹配项,则返回 null(无论是否有修饰符 g)。

如果没有匹配项,我们不会收到一个空数组,而是会收到 null。

javascript 复制代码
let matches = "JavaScript".match(/HTML/); // = null

if (!matches.length) { // Error: Cannot read property 'length' of null
  console.log("Error in the line above");
}

如果我们希望的结果始终是数组,可以这样写:

javascript 复制代码
let matches = "JavaScript".match(/HTML/) || [];

if (!matches.length) {
  console.log("No matches"); // 现在可以了
}

3.替换:str.replace

str.replace(regexp, replacement) 方法使用 replacement 替换在字符串 str 中找到的 regexp 的匹配项(如果带有修饰符 g 则替换所有匹配项,否则只替换第一个)。

javascript 复制代码
// 没有修饰符 g
alert( "We will, we will".replace(/we/i, "I") ); // I will, we will

// 带有修饰符 g
alert( "We will, we will".replace(/we/ig, "I") ); // I will, I wil

l

第二个参数是字符串 replacement。我们可以在其中使用特殊的字符组合来对匹配项进行插入:

符号 在替换字符串中的行为

$& 插入整个匹配项

$` 插入字符串中匹配项之前的字符串部分

$' 插入字符串中匹配项之后的字符串部分

$n 如果 n是一个 1-2位的数字,则插入第 n 个分组的内容

$< name> 插入带有给定 name的括号内的内容

插入字符 $

示例:

javascript 复制代码
console.log( "I love HTML".replace(/HTML/, "$& and JavaScript") ); // I love HTML and JavaScript
console.log( "I love HTML".replace(/HTML/, "$` and JavaScript") ); // I love I love and JavaScript
console.log( "I love HTML".replace(/HTML/, "$' and JavaScript") ); // I love and JavaScript

4.测试:regexp.test

javascript 复制代码
regexp.test(str) 方法寻找至少一个匹配项,如果找到了,则返回 true,否则返回 false。
let str = "I love JavaScript";
let regexp = /LOVE/i;
console.log( regexp.test(str) ); // true

小节

● 正则表达式由模式和可选择修饰符构成:g、i、m、u、s 和 y。

●没有修饰符和特殊符号(稍后我们会学到),那么正则表达式的搜索和子字符串的搜索相同。

●str.match(regexp)方法寻找匹配项:如果带有修饰符 g,则会返回所有匹配项,否则只会返回第一个匹配项。

● str.replace(regexp,replacement) 方法使用 replacement 替换 regexp 的匹配项:如果带有修饰符

g,则会替换所有匹配项,否则只会替换第一个匹配项。

● regexp.test(str) 方法用于测试,如果找到至少一个匹配项则返回 true,否则返回 false。

二、字符类

字符类(Character classes) 是一种特殊的符号,匹配特定集合中的任何符号。

首先,让我们探索"数字"类。它写为 \d,对应于"任何一位数字"。

例如,让我们找到电话号码的第一个数字:

javascript 复制代码
let str = "+7(903)-123-45-67";

let regexp = /\d/;

console.log( str.match(regexp) ); // 7

如果没有修饰符g,那么正则表达式仅查找第一个匹配项,即第一个数字\d。

这时候可以添加g来查找所有数字:

javascript 复制代码
let str = "+7(903)-123-45-67";

let regexp = /\d/g;

console.log( str.match(regexp) ); // 匹配项构成的数组:7,9,0,3,1,2,3,4,5,6,7

// 让我们将其输出为纯数字构成的电话号码:
console.log( str.match(regexp).join('') ); // 79031234567

这是数字的字符类。还有其他字符类。

最常用的是:

\d("d" 来自 "digit") 数字:从 0 到 9 的字符。

\s("s" 来自 "space")空格符号:包括空格,制表符 \t,换行符 \n 和其他少数稀有字符,例如 \v、\f 和 \r。

\w("w" 来自 "word") "单字"字符:拉丁字母或数字或下划线 _。非拉丁字母(如西里尔字母或印地文)不属于 \w。例如,\d\s\w 表示"数字",后跟"空格字符",后跟"单字字符",例如 1 a。

正则表达式可能同时包含常规符号和字符类。

例如,CSS\d 匹配 CSS 后面带有一个数字的字符串:

javascript 复制代码
let str = "Is there CSS4?";
let regexp = /CSS\d/

console.og( str.match(regexp) ); // CSS4

我们还可以使用更多字符类:

javascript 复制代码
console.log( "I love HTML5!".match(/\s\w\w\w\w\d/) ); // ' HTML5'

1.匹配项(每个正则表达式字符类都有对应的结果字符):

反向类

对于每个字符类,都有一个"反向类",用相同的字母表示,但是大写的。

"反向"表示它与所有其他字符匹配,例如:

\D : 非数字:除\d以外的任何字符,例如字母

\S : 非空格符号:除 \s 以外的任何字符,例如字母。

\W : 非单字字符:除 \w 以外的任何字符,例如非拉丁字母或空格。

这个时候就可以使用\D来查找非数字并且将其从字符串中删除:

javascript 复制代码
let str = "+7(903)-123-45-67";

console.log( str.replace(/\D/g, "") ); // 79031234567

点(.)匹配"任何字符"

点 . 是一种特殊字符类,它与"除换行符之外的任何字符"匹配(只匹配一个字符)。

javascript 复制代码
console.log("Z".match(/./)) ; //Z

或者在正则表达式中间:

javascript 复制代码
let regexp = /CS.4/;

console.log( "CSS4".match(regexp) ); // CSS4
console.log( "CS-4".match(regexp) ); // CS-4
console.log( "CS 4".match(regexp) ); // CS 4(空格也是一个字符)

点表示"任何字符",而不是"缺少字符"。必须有一个与之匹配的字符:

javascript 复制代码
console.log( "CS4".match(/CS.4/) ); // null,没有匹配项,因为这里没有与点匹配的字符
console.log( "CSSS4".match(/CS.4/) ); // null,没有匹配项,因为只能匹配一个字符这里中间有两个S

带有修饰符 "s" 时点字符类匹配任何字符

默认情况下,点与换行符 \n 不匹配。

例如,正则表达式 A.B 匹配 A,然后匹配 B 和它们之间的任何字符,除了换行符\n:

javascript 复制代码
console.log( "A\nB".match(/A.B/) ); // null(无匹配项)

如果要匹配任何字符,那么就可以使用修饰符s,如果有s修饰符那么点 .就可以匹配任何字符

javascript 复制代码
console.log("A\nB".match(/A.B/s) ) // A\nB 

' 注意:这里的点依旧只可以匹配一个字符,如果有多个字符,那么结果会是 n u l l ,如果要匹配多个字符,那么字符数与点的数量相同。 ` 注意:这里的点依旧只可以匹配一个字符,如果有多个字符,那么结果会是null,如果要匹配多个字符,那么字符数与点的数量相同。 '注意:这里的点依旧只可以匹配一个字符,如果有多个字符,那么结果会是null,如果要匹配多个字符,那么字符数与点的数量相同。`

示例:

javascript 复制代码
console.log("ACMB".match(/A..B/s) ) // ACMB

三、Unicode:修饰符 "u" 和类 \p{...}

JavaScript 对字符串使用 Unicode 编码。大多数字符使用 2 个字节编码,但这种方式只能编码最多 65536 个字符。

这个范围不足以对所有可能的字符进行编码,这就是为什么使用 4 个字节对一些罕见的字符进行编码,比如 𝒳(数学符号 X)或 😄(笑脸),一些象形文字等等。

字符 Unicode Unicode 中的字节数

a 0x0061 2

≈ 0x2248 2

𝒳 0x1d4b3 4

𝒴 0x1d4b4 4

😄 0x1f604 4

1.Unicode 属性 \p{...}

Unicode 中的每个字符都有很多属性。它们描述了字符所属的"类别",包含了关于字符的各种信息。

例如,如果一个字符具有 Letter 属性,这意味着这个字符归属于(任意语言的)字母表。而 Number 属性则表示这是一个数字:也许是阿拉伯数字,亦或是中文数字,等等。

我们可以查找具有某种属性的字符,写作 \p{...}。为了使用 \p{...},一个正则表达式必须使用修饰符 u。

javascript 复制代码
let str = "A ბ ㄱ";

alert( str.match(/\p{L}/gu) ); // A,ბ,ㄱ
alert( str.match(/\p{L}/g) ); // null(没有匹配项,因为没有修饰符 "u")

以下是主要的字符类别和它们对应的子类别:

● 字母(Letter)L:

○ 小写(lowercase)Ll,

○ 修饰(modifier)Lm,

○ 首字母大写(titlecase)Lt,

○ 大写(uppercase)Lu,

○ 其它(other)Lo。

● 数字(Number)N:

○ 十进制数字(decimal digit)Nd,

○ 字母数字(letter number)Nl,

○ 其它(other)No。

● 标点符号(Punctuation)P:

○ 连接符(connector)Pc,

○ 横杠(dash)Pd,

○ 起始引号(initial quote)Pi,

○ 结束引号(final quote)Pf,

○ 开(open)Ps,

○ 闭(close)Pe,

○ 其它(other)Po。

● 标记(Mark)M(accents etc):

○ 间隔合并(spacing combining)Mc,

○ 封闭(enclosing)Me,

○ 非间隔(non-spacing)Mn。

● 符号(Symbol)S:

○ 货币(currency)Sc,

○ 修饰(modifier)Sk,

○ 数学(math)Sm,

○ 其它(other)So。

● 分隔符(Separator)Z:

○ 行(line)Zl,

○ 段落(paragraph)Zp,

○ 空格(space)Zs。

● 其它(Other)C:

○ 控制符(control)Cc,

○ 格式(format)Cf,

○ 未分配(not assigned)Cn,

○ 私有(private use)Co,

○ 代理伪字符(surrogate)Cs。

也有其它派生的类别,例如:

● Alphabetic(Alpha),包含了字母 L,加上字母数字 Nl(例如 Ⅻ ------ 罗马数字 12),加上一些其它符号 Other_Alphabetic(OAlpha)。

● Hex_Digit 包括 16 进制数字 0-9,a-f。

● ......等等。

Unicode 支持很多不同的属性,列出整个清单需要占用大量的篇幅,因此在这里列出相关的链接:

● 列出一个字符的所有属性:https://unicode.org/cldr/utility/character.jsp.

● 按照属性列出所有的字符:https://unicode.org/cldr/utility/list-unicodeset.jsp.

● 属性的对应缩写形式:https://www.unicode.org/Public/UCD/latest/ucd/PropertyValueAliases.txt.

● 以文本格式整理的所有 Unicode 字符,包含了所有的属性:https://www.unicode.org/Public/UCD/latest/ucd/.

举例:16进制数

查找16进制数,写作 xFF 其中 F 是一个 16 进制的数字(0...9 或者 A...F)。

一个 16 进制数字可以表示为 \p{Hex_Digit}:

javascript 复制代码
let regexp = /x\p{Hex_Digit}\p{Hex_Digit}/u;

alert("number: xAF".match(regexp)); // xAF

举例:中文字符

有一个 Unicode 属性 Script(一个书写系统),这个属性可能有一个值:Cyrillic、Greek、Arabic、Han(中文)等等,这里是一个完整的列表。

要在给定的书写系统中查找字符,我们需要使用 Script=,例如对于西里尔字母:\p{sc=Cyrillic},中文象形文字:\p{sc=Han},等等。

javascript 复制代码
let regexp = /\p{sc=Han}/gu; // 返回中文象形文字

let str = `Hello Привет 你好 123_456`;

alert( str.match(regexp) ); // 你,好

举例:货币

表示货币的字符,例如 $、€ 和 ¥,具有 Unicode 属性 \p{Currency_Symbol},缩写为 \p{Sc}。

javascript 复制代码
let regexp = /\p{Sc}\d/gu; //查找所有的货币符号以及数字

let str = `Prices: $2, €1, ¥9`;

alert( str.match(regexp) ); // $2,€1,¥9

总结

修饰符 u 表示启用正则表达式中对 Unicode 的支持。

这意味着两件事:

  1. 4 个字节长的字符被以正确的方式处理:被看成单个字符,而不是 2 个 2 字节长的字符。
  2. Unicode 属性可以被用于查找:\p{...}。
    有了 unicode 属性我们可以查找给定语言中的词,特殊字符(引用,货币)等等。
    四、锚点:字符串开始 ^ 和末尾 插入符号 \^ 和美元符号 在正则表达式中具有特殊的含义。它们被称为"锚点"。
    插入符号 ^ 匹配文本开头,而美元符号 则匹配文本末尾。 let str = "张三"; console.log(/\^张/.test(str)) //true 判断是否以张开头 let str1 = "李四"; alert( /四 / . t e s t ( s t r 1 ) ) ; / / t r u e 判断是否以四结尾测试完全匹 配 . . . /.test(str1) ); // true 判断是否以四结尾 测试完全匹配 \^... /.test(str1));//true判断是否以四结尾测试完全匹配...结合使用。示例如下: //测试一个字符串是否是 12:34(\\d\\d:\\d\\d) 格式的时间 let time1 = "01:13"; let time2 = "01:134"; let regexp = /\^\\d\\d:\\d\\d/;
    console.log(regexp.test(time1)) // true
    console.log(regexp.test(time2))// false

五、锚点 ^ $ 的多行模式,修饰符 "m"

多行模式由修饰符 m 启用。

它只影响 ^ 和 $ 的行为。

在多行模式下,它们不仅仅匹配文本的开始与末尾,还匹配每一行的开始与末尾。

搜索行的开头

javascript 复制代码
let str = `1one
2two
3three`;  //注意:每行内容一定要在编辑器最左边,否则会默认为是一行内容中间为空格
console.log(str.match(/^\d/gm)) // [1,2,3]

没有修饰符 m 时,仅会匹配第一个数字:

javascript 复制代码
let str = `1st place: Winnie
2nd place: Piglet
3rd place: Eeyore`;

console.log( str.match(/^\d/g) ); // 1

注意:"行的开头"表示"就在换行符之后":多行模式下的测试 ^ 匹配所有以换行符 \n 开头的位置。以及在文本开始的位置。

搜索行的末尾 $

正则表达式 \d$ 寻找每行的最后一个数字

javascript 复制代码
let str = `red:1
yellow:2
green:3
`;
//没有修饰符 m,那么美元符 $ 将只会匹配整个文本的末尾,所以只有最后一个数字会被匹配。
consoel.log(str.match(/\d$/gm));//[1,2,3]

注意:"行的末尾"表示"就在换行符之前":多行模式下的测试 $ 匹配所有以换行符 \n 结尾的位置。以及在文本末尾的位置。

搜索 \n 而不是 ^ $

要寻找新的一行,我们不仅可以使用锚点 ^ 和 $,也可以使用换行符 \n。

javascript 复制代码
let str = `Winnie: 1
Piglet: 2
Eeyore: 3`;

console.log( str.match(/\d\n/g) ); // 1\n,2\n

区别:

  1. 这里只匹配到了两个,因为3之后没有换行了
  2. 现在每个匹配项都包含换行符。与锚点^ $不同,锚点只测试条件(行的开始与末尾),而\n是一个字符,因此结果中有\n。 我们需要结果中有换行符时,使用 \n。而锚点则用于在行的开头/末尾查找某些内容。

六、结束语

本节正则表达式就到此结束了,但是正则表达式的内容还不只这些,下一节会继续讲解正则表达式的使用,欢迎小伙伴们来参阅,不要忘记点赞加加关注哦。

相关推荐
TOWNST11 分钟前
正则表达式使用知识(日常翻阅)
java·python·正则表达式
小陈同学呦20 分钟前
聊聊vue中的keep-alive
前端·javascript·面试
调试大师(八岁习武)23 分钟前
前端开发中的问题排查与定位:HTML、CSS、JavaScript(报错的解决方式)
javascript·css·html
XU磊26037 分钟前
深入 Java 正则表达式源码:透视 Matcher.group(int) 的分组提取机制
正则表达式
彭铖洋41 分钟前
idea版的cursor:Windsurf Wave 7
javascript·reactjs
喝拿铁写前端43 分钟前
你以为你在封装组件,其实你在引入混乱
前端·架构
Json____1 小时前
智慧酒店企业站官网-前端静态网站模板【前端练习项目】
前端·网站模板·静态网站·企业站·智慧酒店网站
不爱说话郭德纲1 小时前
没有CICD,怎么自动化部署?
前端·javascript·vue.js
Aotman_1 小时前
Vue表单组件el-form校验规则rules,条件判断rules表单验证显示必填或非必填
javascript·vue.js·elementui