玩转正则表达式,就是这么简单

在平时开发中,正则表达式用的好能节省很大的工作量,举个例子
将字符串格式化成数组(数字不格式化), 例如: 张123四 => ["张", "123", "四"];
如果使用原生js的话,需要这么写:

function transArrExcluNnm(str){
  var arr = str.split('');
  var arrnew = [],numstr = '',isNum=false;;
  for(var i=0;i<arr.length;i++){
    var item  = arr[i];
    if(/\d/.test(item)){
      isNum = true;
      numstr = numstr + String(item);
      continue
    }else{
      if(isNum){arrnew.push(numstr);numstr='';isNum=false;}
      arrnew.push(item)
    }
  }
  return arrnew;
}

 transArrExcluNnm('我1说123木头09人');
// ["我", "1", "说", "123", "木", "头", "09", "人"]

随随便便都要是多行代码,如果使用正则,只需要一行就搞定了str.match(/\d+|[^0-9]/gi);
'我1说123木头09人'.match(/\d+|[^0-9]/gi); // ["我", "1", "说", "123", "木", "头", "09", "人"]

所以作为一个开发人员,掌握正则的基本用法,可以提高代码质量.

那么什么是正则呢?

正则表达式(regular expression)描述了一种字符串匹配的模式(pattern),可以用来检查一个串是否含有某种子串、将匹配的子串替换或者从某个串中取出符合某个条件的子串等

作为一个开发人员,怎么调试正则呢?(博主是直接打开浏览器,在console里面调试)

当然喜欢用调试工具的也可以访问这:http://rubular.com/ 

好了言归正传,我们来说说正则中的常用的正则表达式以及语法

使用一个正则表达式字面量,其由包含在斜杠之间的模式组成,如下所示:

var re = /ab+c/;

脚本加载后,正则表达式字面量就会被编译。当正则表达式保持不变时,使用此方法可获得更好的性能。
或者调用RegExp对象的构造函数,如下所示:

var re = new RegExp("ab+c");

在脚本运行过程中,用构造函数创建的正则表达式会被编译。如果正则表达式将会改变,或者它将会从用户输入等来源中动态地产生,就需要使用构造函数来创建正则表达式。

正则表达式中的特殊字符

\d:数字 
\w:字母或数字 
\s:空格或tab 
.:任意字符 
[0­9a­zA­z\_]:0到9或小写字母或大写字母或下划线 
A|B:A或B(例如(P|p)ython匹配'Python'或'python') 
\:转译字符
*:0个或多个 
+:1个或多个 
?:0个或1个 
{n}:正好N个 
{n,m}:n至m个
|:匹配左右任意一个表达式
(ab):将括号中字符作为一个分组
\num:引用分组num匹配到的字符串
    \n:表示第n个被捕获括号匹配的子字符串,而replace则使用$n来匹配括号里的子串
    例:/(a)(b)\d*\1\2/ : \1和\2分别表示第一个括号和第二个括号中的规则 即: /(a)(b)\d*(a)(b)/
        /(a)(b)\d*\1\2/.test('ab0ab') // true;
        /(a)(b)\d*\1\2/.test('ab0ee') // false
    例:'123-李四'.replace(/(\d+)\-(\D+)/,'$2,$1'); // "李四,123"
    其中$1匹配的是(\d+)的结果,$2匹配的是(\D+)的结果

(?P<name>):分组起别名 
(?P=name):引用别名为name分组匹配到的字符串
^:行的开头,
^\d表示必须以数字开头 
$:行的结尾,例如,/t$/ 并不会匹配 "eater" 中的 't',但是会匹配 "eat" 中的 't'。
\d$表示必须以数字结尾
^在[]里还可表示反向字符范围:[^a‐z] #匹配不在a‐z的范围的字符

例如匹配010­123456的正则为:\d{3}\­\d{3,8} 
匹配手机号:1[358]\d{9} 
匹配图片:r"https://.*?\.[jpng]{3}"

使用正则表达式的方法

方法 描述
exec 一个在字符串中执行查找匹配的RegExp方法,它返回一个数组(未匹配到则返回 null)。
test 一个在字符串中测试是否匹配的RegExp方法,它返回 true 或 false。
match 一个在字符串中执行查找匹配的String方法,它返回一个数组,在未匹配到时会返回 null。
matchAll 一个在字符串中执行查找所有匹配的String方法,它返回一个迭代器(iterator)。
search 一个在字符串中测试匹配的String方法,它返回匹配到的位置索引,或者在失败时返回-1。
replace 一个在字符串中执行查找匹配的String方法,并且使用替换字符串替换掉匹配到的子字符串。
split 一个使用正则表达式或者一个固定字符串分隔一个字符串,并将分隔后的子字符串存储到数组中的 String 方法。

search/split/test/replace 

// search: str.search(reg)
var str="Visit W3School!"
str.search(/W3School/) // 6
str.search(/sdf/) // -1

// split: str.split(reg)
var str="貂蝉love吕布" 
var result = str.split(/[a-z]+/g) // 以规则/[a-z]+/g来分割str
// 等价于var result = str.split(new RegExp("[a-z]+", "g"))
console.log(result) //  ["貂蝉", "吕布"]

// test: reg.test(str)
/\d/.test('Visit W3School!'); // true

// replace: str1.replace(reg, str2)
'Visit W3School!'.replace(/\d/, '替换数字'); // "Visit W替换数字School!"

match/exec
由下面的运行结果可以看出,
exec:不管正则是否加全局,返回的内容是一样的
match:
    非全局正则,可以返回捕获组,也就是正则里面()里面的内容,但不能多次匹配;
    全局正则,可以多次匹配,但不返回捕获组;

matchAll :返回一个数组集合,使用...展开的话会发现,里面是匹配到的子穿

正则表达式执行后的返回信息

var myRe = /d(b+)d/g; // var myRe  = new RegExp("d(b+)d", "g")
var myArray = myRe.exec("cdbbdbsbz");

console.log(myArray) // ["dbbd", "bb", index: 1, input: "cdbbdbsbz", groups: undefined]
console.log(myRe.lastIndex) // 5
console.log(myRe.source) // "d(b+)d"
对象 属性或索引 描述 在例子中对应的值
myArray   匹配到的字符串和所有被记住的子字符串(即每一个括号中的匹配到的)。 ["dbbd", "bb"]
index 在输入的字符串中匹配到的以0开始的索引值。 1
input 初始字符串。 "cdbbdbsbz"
[0] 匹配到的所有字符串(并不是匹配后记住的字符串)。注:原文"The last matched characters.",应该是原版错误。匹配到的最终字符。 "dbbd"
myRe lastIndex 下一个匹配的索引值(必须以变量保存的形式才有值,像/d(b+)d/g.lastIndex的话结果就是0)。注意:这个属性只有在使用g参数时可用 5
source 模式文本。在正则表达式创建时更新,不执行。 "d(b+)d"

使用括号的子字符串匹配
一个正则表达式模式使用括号,将导致相应的子匹配被记住。例如,/a(b)c /可以匹配字符串“abc”,并且记得“b”。回调这些括号中匹配的子串,使用数组元素[1],……[n]。
使用括号匹配的子字符串的数量是无限的。返回的数组中保存所有被发现的子匹配。下面的例子说明了如何使用括号的子字符串匹配。
下面的脚本使用replace()方法来转换字符串中的单词。在匹配到的替换文本中,脚本使用替代的$ 1,$ 2表示第一个和第二个括号的子字符串匹配

var re = /(\w+)\s(\w+)/;
var str = "John Smith";
var newstr = str.replace(re, "$2, $1");
console.log(newstr); // Smith, John

通过标志进行高级搜索,下面是正则表达式标志 

g 全局搜索。
i 不区分大小写搜索。
m 多行搜索。
s 允许 . 匹配换行符。
u 使用unicode码的模式进行匹配。
y 执行“粘性”搜索,匹配从目标字符串的当前位置开始,可以使用y标志。

为了在正则表达式中包含标志,请使用以下语法:

var re = /pattern/flags;
// 或者
var re = new RegExp("pattern", "flags");

值得注意的是,标志是一个正则表达式的一部分,它们在接下来的时间将不能添加或删除。

var re = /\d+|[^0-9]/g; // 等价于 var re = new RegExp("\d+|[^0-9]", "g");
var str = '我1说123木头09人';
var myArray = str.match(re);
console.log(myArray);

// ["我", "1", "说", "123", "木", "头", "09", "人"]

一些简单匹配

// 简单的匹配
var s1 = 'abc‐123456' 
var m1 = /^[a-z]{3}‐\d{3,6}$/ 
s1.match(m1) 
// 结果: ["abc‐123456", index: 0, input: "abc‐123456", groups: undefined]

// | 的用法
"08".match(/[1‐9]?\d$|100/)
// 结果: ["8", index: 1, input: "08", groups: undefined]

// 匹配开头结尾: 
"<html>hh</html>".match(/<[a-zA-Z]*>\w*<\/[a-zA-Z]*>/)
// 结果: ["<html>hh</html>", index: 0, input: "<html>hh</html>", groups: undefined]

// 组的匹配:
'abc‐123456'.match(/^([a-z]{3})‐(\d{3,6})$/) 
// 结果: ["abc‐123456", "abc", "123456", index: 0, input: "abc‐123456", groups: undefined]

// 贪婪匹配: 正则默认使用贪婪匹配,也就是匹配尽可能多的字符:
'12300'.match(/^(\d+)(0*)$/) 
// 结果: ["12300", "12300", "", index: 0, input: "12300", groups: undefined]
//前面的\d+采用贪婪匹配把所有的数字全给匹配了,导致第二组的0*匹配了个空字符串,如果想让后面的0* 也匹配到,可用?使前面的\d+不使用贪婪匹配:
'12300'.match(/^(\d+?)(0*)$/) 
// 结果: ["12300", "123", "00", index: 0, input: "12300", groups: undefined]

// 匹配一个变量
const sendPostKey = '西湖';
const PosKey = '杭州西湖商圈';
const re = new RegExp(sendPostKey, 'gi');
const buleStrHtml = PosKey.replace(re, '<span class="col2a86e8">' + sendPostKey  + '</span>');
console.log(buleStrHtml); //杭州<span class="col2a86e8">西湖</span>商圈"

如果遇到非正常的html格式字符串,匹配出错

// 如果遇到非正常的html格式字符串,匹配出错
"<html>hh</htmlbalabala>".match(/<([a-zA-Z]*)>\w*<\/\1>/)
// 结果: null

"<html>hh</html>".match(/<([a-zA-Z]*)>\w*<\/\1>/)
// 结果: ["<html>hh</html>", "html", index: 0, input: "<html>hh</html>", groups: undefined]

/*
注意:这个\1  \2......  都要和正则表达式集合()一起使用
简单的说就是
\1表示重复正则第一个圆括号内匹配到的内容
\2表示重复正则第二个圆括号内匹配到的内容
*/

猜你喜欢

转载自blog.csdn.net/l284969634/article/details/104823778
今日推荐