正则表达式使用汇总---javascript篇

最近在做web开发,前台js和后台python经常会使用正则表达式,来处理一些字符的问题,比如查询,替换,匹配等场景,本文将汇总在开发中正则表达式使用的方法,并对js和python在实现同样功能时,两者的方法区别等做一下整理。

javascript

先说明一下js中正则表达式的基本使用,首先是构造一个正则表达式,有两种方法,分别如下:

  1. 使用正则表达式字面量,包含在斜杠之间的模式组成,例如如下:
// 格式: /pattern/flags  其中flags包括: i / g / m

const regex_1 = /[a-z]+/;
const regex_2 = /[a-z]+/gi;
  1. 使用 RegExp 对象来构造,例如如下:
// 格式: new RegExp(pattern [, flags])

let regex_1 = new RegExp("[a-z]+\\d+");
let regex_2 = new RegExp(/[a-z]+\d+/, "gi");
let regex_3 = new RegExp("[a-z]+\\d+", "gi")

可以看出使用斜杆方法是不能传入变量的,但是通过RegExp中使用字符串的方式,可以传入变量,来丰富使用场景。例如如下用法

let regex = new RegExp("^\\" + site_url + "event_list\/[0-9]+\/alert_detail\/[0-9]+\/", 'i');

下面摘取一些特殊符号的使用说明如下,具体点击查阅.

符号 说明
. 小数点符号匹配除 换行符 之外的任何单个字符
\w 匹配一个单字字符(字母、数字、下划线),等价于 [a-zA-Z0-9_]
\W 匹配一个非单字字符,等价与 [^a-zA-Z0-9_]
\s 匹配一个空白字符,包括:空格、制表符、换页符和换行符
\b 匹配一个词的边界,匹配词的边界并不包含在匹配的内容中
(x) 匹配 x 并且记住匹配项,括号称为捕获括号
x(?=y) 正向肯定查找,匹配 x 仅仅当 x 后面跟着 y
x(?!y) 正向否定查找,匹配 x 仅仅当 x 后面不跟着 y
(?:y)+ 表示匹配y一次或多次,但是不记住匹配项 y,与 (x)+ 的区别就在于是否有记住匹配项
x|y 匹配 x 或者 y

注意: 使用 (x) 捕获括号时,在正则表达式中,还可以使用 \1 \2 等来表示子表达式的匹配项,例如如下例子:

let regex = new RegExp(/([\w]+)\s+([\w]+)\s+\1\s+\2/, 'g');
let str = "hello world hello world ...";

regex.exec(str);
// 结果为: ["hello world hello world", "hello", "world", index: 0, input: "hello world hello world ...", groups: undefined]

regex.exec(str);
// 结果为: null

javascript方法汇总比较

下面先汇总得出各个方法比较和使用场景。

方法 用法 返回值 使用场景 注意事项
match str.match(regexp) Array / null 获取第一次匹配的子串,比如想获取子表达式匹配的文本
exec regexp.exec(str) Array / null 循环获取匹配的子串,也能够获取子表达式匹配的文本
search str.search(regexp) Number / -1 获取第一次匹配到的子串的下标位置 此处的regexp可以有多种定义方式
test regexp.test(str) true / false 判断某个正则表达式在字符串中是否有匹配的子串
replace str.replace(regexp/substr, replacement) newstr 替换字符串中某些条件的子字符串 不会改变原字符串str内容

提供几个javascript的正则表达式使用网站,可视化正则表达式在线解析正则匹配结果分析在线解析正则匹配结果

match

match 方法将检索字符串str,找到一个或多个与regexp匹配的文本(如果flags中有g那么就会全局匹配)

如果没有g,那么match方法就只能在str中执行一次匹配,如果没有找到则返回null,否则返回一个Array,其中存放了与他找到的匹配文本有关的信息,例如如下结果,其中 res[0] 表示存放的是匹配文本,res[1]表示存放的是与正则表达式regex里子表达式([a-z]+)匹配的文本;res['index']表示存放的是匹配文本的其实字符在str中的位置;res['input']表示存放的是str的引用。

let str = "I'm a chinese.";
let regex = new RegExp(/\s+([a-z]+)\s+/);
let res = str.match(regex);

// res结果为: [" a ", "a", index: 3, input: "I'm a chinese.", groups: undefined]

如果有g,那么match将执行全局检索,找到str中的所有匹配子字符串。如果没有找到则返回null;否则返回一个Array,存放的是所有匹配子串。例如如下例子:

let str = "I'm a chinese.";
let regex = new RegExp(/\s+([a-z]+)\s+/, 'g');
let res = str.match(regex);

// res结果为: [" a "]

所以在全局检索模式下,match既不提供与子表达式匹配的文本的信息,也不返回每个匹配子串的位置,如果需要这些信息,可以使用 exec 方法获取。

exec

exec方法用于检索字符串中的正则表达式的匹配,返回一个数组,用于存放匹配的结果;如果没有找到匹配,返回null。
当使用非全局正则表达式时,execmatch 的返回结果是一样的,只是调用方式不同而已。
当使用全局正则表达式时,exec会使 lastIndex 在正则表达式匹配到字符串的最后一个字符的下一个位置,这样可以通过反复调用 exec 方法来遍历字符串的所有匹配文本。
exec 再也找不到匹配的文本时,返回null,并把 lastIndex 属性重置0,所以如果反复循环调用 exec 的话,那么得到的结果也会是一个循环的数值,结果格式可能为:
['m', ...] ['a', ...] ['chinese', ...] null ['m', ...] ['a', ...] ['chinese', ...] null ...

另外,无论正则表达式是否是全局,调用 exec 方法,都会把完整的细节添加到它的返回数组中。例如如下例子:

let str = "I'm a chinese";
let regex = new RegExp(/[a-z]+/, 'g');

regex.exec(str)
// 结果为: ["m", index: 2, input: "I'm a chinese", groups: undefined]

regex.exec(str)
// 结果为: ["a", index: 4, input: "I'm a chinese", groups: undefined]

regex.exec(str)
// 结果为: ["chinese", index: 6, input: "I'm a chinese", groups: undefined]

regex.exec(str)
// 结果为: null

regex.exec(str)
// 结果为: ["m", index: 2, input: "I'm a chinese", groups: undefined]

search

查询字符串中满足条件(字符串或正则表达式)的子字符串,返回值为该子字符串的起始位置,如果没有查找到,则返回 -1
search的传参可以是字符串,也可以是斜杆写法的正则表达式,search会将字符串转化为斜杆写法,例如如下三种写法是等价的:

// 写法一
let str = "I'm a chinese.";
let regex = new RegExp(/\s+([a-z]+)\s+/, 'i');
let res = str.search(regex);

// 写法二
let str = "I'm a chinese.";
let res = str.search(/\s+([a-z]+)\s+/i);

// 写法三
let str = "I'm a chinese.";
let res = str.search("\\s+([a-z]+)\\s+", "i");

// 以上结果都为: 3

test

test方法用于检测一个字符串是否匹配某个模式,如果字符串中含有匹配的文本,则返回true,否则返回false。
例如如下例子:

let str = "I'm a chinese.";
let regex = new RegExp(/\s+([a-z]+)\s+/, 'i');
let res = regex.test(str);

// res结果为: true

replace

replace 用于替换字符的场景,用一些字符替换另一些字符,或替换一个与正则表达式匹配的子串。返回值为替换之后的字符串结果。
例如如下例子:

// 语法: str.replace(regexp/substr, replacement) 
// 其中 regexp/substr 表示此处既可以是正则表达式也可以是字符串,如果是substr那么不会转化为RegExp对象,而是作为普通的字符串
// replacement 既可以是普通字符串,也可以是替换函数

let str = "I'm a chinese.";
let res = str.replace(/\b([\w']+)\b/g, "[$1]");

// res结果为: "[I'm] [a] [chinese]."

// replacment使用函数
let res_f = str.replace(/\b([\w']+)\s+\b/g, item => 
    "[" + item.substring(0,1).toUpperCase() + item.substring(1) + "]");

// res_f结果为: "I'm A Chinese."

这里再举一个通过单词分隔位置来对数字进行英文逗号分隔的效果

let num = 1234567890;
num.toString().replace(/(?=(?!\b)(?:\d{3})+$)/g, ',');

// 当然也可以使用 num.toLocaleString()

当replacement为函数的时候,参数 item 表示的是与regexp匹配的子串,和字符串表示中的 $& 内容一样。
当replacement为字符串时,字符 $ 具有特定的含义,具体如下表:

字符 替换文本
$1 / $2 ... $99 表示与regexp中的第1到第99个子表达式匹配的文本
$& 表示与regexp匹配的子串(注意不是子表达式
$` 表示位于匹配子串左侧的文本
$' 表示位于匹配子串右侧的文本
$$ 表示字符 $
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

推荐阅读更多精彩内容