正则表达式使用汇总---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匹配的子串(注意不是子表达式
$` 表示位于匹配子串左侧的文本
$' 表示位于匹配子串右侧的文本
$$ 表示字符 $
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 204,293评论 6 478
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 85,604评论 2 381
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 150,958评论 0 337
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,729评论 1 277
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,719评论 5 366
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,630评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 38,000评论 3 397
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,665评论 0 258
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,909评论 1 299
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,646评论 2 321
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,726评论 1 330
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,400评论 4 321
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,986评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,959评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,197评论 1 260
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 44,996评论 2 349
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,481评论 2 342

推荐阅读更多精彩内容