toFrankie / blog

种一棵树,最好的时间是十年前。其次,是现在。
20 stars 1 forks source link

JavaScript 正则表达式 #231

Open toFrankie opened 1 year ago

toFrankie commented 1 year ago

正则表达式(Regular Expressions)是用于匹配字符串中字符组合的模式。在 JavaScript 中,正则表达式也是对象。这些模式被用于 RegExp 的 exec 和 test 方法, 以及 String 的 matchmatchAllreplacesearch 和 split 方法。

创建正则表达式的方式有两种:

// 正则表达式字面量
const re = /ab+c/

// 使用 RegExp 对象的构造函数
const re = new RegExp("ab+c")

正则表达式中的特殊字符

直接量字符

如果想在正则表达式中使用特殊的标点符号,必须在他们之前加上一个 \ 进行转义。

字符类

将单独的直接复放进中括号([...])内就可以组合成字符类。一个字符类和它所包含的任何一个字符都匹配。正式表达式 /[abc]/ 和字母 "a""b""c" 中的任何一个都匹配,另外还可以定义否定字符类,这些类匹配的是除那些包含在中括号之内的字符外的所有字符。定义否定字符尖(^)时,要将一个 ^ 符号作为从左中括号算起的第一个字符。

由于某些字符类非常常用,所以 JavaScript 的正则表达式语法包含一些特殊字符和转义序列来表示这些常用的类。比如 \s 匹配的是空白符(包括空格符、制表符、换行符等空白符),\S 匹配的是除空白符之外的任意字符。

复制

用以上的正则表达式语法,可以把两位数描述成 /\d\d/,把四位数描述成 /\d\d\d\d/,但是我们还没有一种方法可以用来描述具有任意多位数的数字或者是一个字符串,这个字符串由三个字符以及跟随在字母后的一位数字构成。这些复杂的模式使用的正则表达式语法指定了改表达式中每个元素要重复出现的次数。

指定复制的字符总是出现在它们所作用的模式后面。由于某种复制类型相对常用。所以有一些特殊的字符专门用于表示它们。比如 + 匹配的就是复制前一模式一次或多次的模式下。

先看写例子:

复制字符的几种方式:

选择、分组、引用

正则表达式的语法还包括指定选择项,对子表达式分组和引用前一子表达式的特殊字符。字符 | 用于分隔供选择的字符,例如:/ab|cd|ef/ 匹配的是 "ab" 或者是 "cd" 又或者是 "ef" 字符串。再比如:/\d{3}|[a-z]{4}/ 匹配的是要么是一个三位数字,要么是四个小写字母。

在正则表达式中,括号((...))具有几种作用:

  1. 它的主要作用是把单独的项目分组成子表达式,以便可以像处理一个独立的单元那种用 *+? 来处理那些项目。例如:/java(script)?/ 匹配的是字符串 "java",其后的既可以有 "script",也可以没有。再比如,/(ab|cd)+|ef/ 匹配的既可以是字符串 "ef",也可以是字符串 "ab" 或者 "cd" 的一次或多次重复。

  2. 括号的第二个用途是,在完整的模式中定义子模式。当一个正则表达式成功地和目标字符串相匹配是,可以从目标串中抽出和括号中的子模式相匹配的部分。例如,假定我们正在检索的模式是一个或多个字母后面跟随一位或多位数组,你们我们可以使用模式 /[a-z]+\d+/。但是由于假定我们真正关心的是每个匹配尾部的数字,那么如果我们将模式的数字部分放在括号中 /[a-z]+(\d+)/,我们就可以从所检索到的任何匹配中抽取数字了,之后我们会对此进行解析的。

  3. 代括号的另一个用途是,允许我们在同一正则表达式的后面引用前面的子表达式。这是通过在字符串 \ 后加一位或多位数字来实现的。数字指的是代括号的子表达式在正则表达式中的位置。例如:\1 引用的的是第一个代括号的子表达式,\3 引用的是第三个代括号的子表达式。注意,由于子表达式可以嵌套在其他子表达式中,所以它的位置是被计数的左括号的位置。

例如,在下面的正则表达式被指定为 \2/([Jj]ava[Ss]cript)\sis\s(fun\w*)/,对正则表达式中前一子表达式的引用所指定的并不是那个子表达式,而是与那个模式相匹配的文本。这样,引用就不只是帮助你输入正则表达式的重复部分的快捷方式了,它还实施了一条规约,那就是一个字符串各个分离的部分包含的是完全相同的字符。例如:/['"][^'"]['"]/ 匹配的就是位于单引号或者双引号之内的所有字符。但是它要求开始和结束的引号匹配。(例如两个都是双引号或者都是但引号) 如果要求开始和结束的引号匹配,我们可以使用如下的引用:/(['"])[^'"]*\1/\1 匹配的是第一个代括号的子表达式所匹配的模式。在这个例子中,它实施了一种规约,那就是开始的引号必须和结束的引号相匹配。注意,如果反斜杠后跟随的数字比代括号的子表达式数多,那么它就会被解析为一个十进制的转义序列,而不是一个引用。你可以坚持使用完整的三个字符来表示转义序列,这样就可以避免混淆了。例如 \044,而不是 \44

下面是正则表达式的选择、分组和引用字符:

通过标志进行高级搜索

正则表达式有六个可选参数flags)允许全局和不分大小写搜索等。这些参数既可以单独使用,也能以任意顺序一起使用,并且被包含在正则表达式实例中。

动态创建正则表达式

从用户输入等来源中动态地产生,就需要使用构造函数来创建正则表达式。

// 假设需求是生成一个正则表达式:/temp/

// 此时我们手上有一个字符串 "temp"
var str = 'temp';

// 这种方式是不对的,得到的只是一个 "/temp/" 字符串。
var re = '/' + str + '/';

// 应该是这样,才是正则表达式
var re = new RegExp(str);

未完待续...

\s 空白符
\S 非空白符
[\s\S]任意字符
[\s\S]* 0个到任意多个字符
[\s\S]*? 0个字符,匹配任何字符前的位置。

常用正则表达式

// 删除字符串前后第一个空格
str.replace(/(^\s*)|(\s*$)/g, '')

// 删除字符串中所有空格
str.replace(/\s/g, '')

需要转义的字符

需要转义的字符有:\.*^&[]{}? 等。

[ ] \ ^ $ . | ? * + ( )

References