正则表达式

  正则表达式,又叫规则表达式,我们写一个正则表达式,其实就是写一个规则,那么写一个规则干什么呢? 去匹配字符串,就是看看字符串中有哪个部分和我们定义的规则相符合,找到这些匹配的字符,我们就可以进行字符替换删除等操作,如下例子: 找到字符串中的所有数字,转化成字符G.  

let reg = /\d/g; // 定义一种规则,\d 表示数字。
let str = 'a4c5d6'
let strReplaced = str.replace(reg,"G")
console.log(strReplaced)    //  aGcGdG

  可以看到,正则表达式极大地方便了对字符串的操作。JS 是通过内置RegExp对象来支持正则表达式。既然是对象,那就有两种创建方式, 一种是对象字面量,一种是构造函数。

// 对象字面量
let regLiteral = /\d/g;
// 构造函数
let regCons = new RegExp('\\d', "g");

  构造函数使用不是太方便,一般都是使用字面量,只有在事先不确定的情况下需要动态生成时,才需要用到构造函数。

  2, 标识符: 上面的g 就是一个标识符,除了它,还有两个i, m

  g 是global,表示全局匹配。为什么会有这个标识符呢? 因为正则表达式匹配字符串时,默认是惰性匹配,就是,它只要成功匹配到一个,它就不会再进行匹配,把let reg = /\d/g 中的g 去掉,

let reg = /\d/; 
let str = 'a4c5d6'
let strReplaced = str.replace(reg,"G")
console.log(strReplaced)    //  aGc5d6

  可以看到,它只会匹配第一个数字4。从字符串的起始位置开始匹配,只要成功匹配到一个,就停止了, 即使字符串后面还有和正则表达式相匹配的,它也不管。加上g 标识符,就告诉正则表达式全部匹配,字符串中只要有和正则表达式相匹配的,就全部进行匹配,对应到替换字符,就是全部替换掉相符合的。

  i,是ignore, 忽略大小写。这很好理解, js就是区分大小写的,如果用一个大写字母去区配字符串的话,它只会去找字符串中的大写字母。如果加上i修饰符,就表示可以忽略大小写,小写字母也是ok的。

// 没有加i标识符,可以看到它只会匹配字符串中的小写a
let reg = /a/g;  
let str = 'aAbbcc'
let strReplaced = str.replace(reg,"G")
console.log(strReplaced)    //  GAbbcc
// 加i标识符,可以看到大写A小写a都会匹配 
let reg = /a/gi;  
let str = 'aAbbcc'
let strReplaced = str.replace(reg,"G")
console.log(strReplaced)    //  GGbbcc

  3, 正则表达式有两种基本字符组成,一种是原义文本字符,一种是元字符。原义文本字符,是指这个字符就是它本来的意思。let reg = /a/, a 就是小写字母a, 它也只会匹配小写字母a, 这就是它本来的意思,没有其他任何意思。 元字符,它是指有特殊含义的字符,如\d, 它不是匹配 一根\和小写字母d 的组合,\d 表示的是任意的数字。 正则表达式中有以下元字符:. * ? ^ 等, 也就是说,这些字符都有特殊的意思.

  4, 字符类

  一般情况下,正则表达式在去匹配字符串的时候,都是一个字符一个字符的去匹配,也就是正则表达式中的一个字符对应字符串的一个字符。 但有时候,我们想让正则表达式中的多个字符去匹配一个字符,也就是,我们字符串中只要出现多个字符中一个就算匹配成功。比如,我们只要求字符串中有数字就行,而不管数字是哪个。这时就要用到[], 中括号中的字符,我们字符串中只要出现一个就ok.

// []只要有中括号中的一个字符就算成功。
let reg = /[0123456789]/g;  
let str = 'a1b2c3d4'
let strReplaced = str.replace(reg,"G")
console.log(strReplaced)    //  aGbGcGdG

可以看到,只要字符串中有一个数字,就算匹配成功。我们把所有的数字一一列出来,比较麻烦,如果有26个字母,我们要列了26个字母,这更麻烦了。还好正则表达式提供了范围的书写,0-9,a-z ,并且还可以连写。

let reg =[0-9a-zA-z]

   在[]中其实还可以用一个字符,那就是^, 它表示取反。[^0-9] 就表示除了0-9之处的任意字符。[^0-9a-zA-z] 则表示除了0-9,a-z A-Z 之外的任意字符。对于这些常用的表示符,正则表达式也提供了一些预定义类,[0-9]表示数字,就可以用\d 来代替,[^0-9] 表示非数字,可以用\D来代替, 还有\s, \w, \W等。 小写形式是什么,大写形式就是它的取反.

  \d, d是digital 表示数字, 那么\D 则表示不是数字; \s, space 表示空白符, \S就表示非空白符. \w, word, 表示单词字符(字母,数字加下划线), \W 表示非单词字符,这里还有一个 点号 . 它表示除回车和换行符之外的任意字符。我们写一个 ab 开始,后面紧跟数字,再后面是任意字符的正则表达式,let reg = /ab\d./

let reg = /ab\d./g;
let string = 'there is ab5td and abds '
let replaceString = string.replace(reg,"A");
console.log(replaceString)  // there is Ad and abds 

  这个正则表达式区配的是ab5t

  5, 边界类

  边界类主要用四个: ^ 表示以什么开始,$表示以什么结尾, \b, boudary 表示单词边界,\B 表示非单词边界。边界就是单词和单词相隔的地方,最明显的就是空格。

写一个例子来看一下可以更为直观。

let reg = /is/g;
let string = 'this is a dog '
let replaceString = string.replace(reg,"IS");
console.log(replaceString)  // thA IS a dog 

  两个is 都被替换掉了,这符合预期。但我们怎么只替换中间的is,中间的is 有一个特点,它是一个单词,因为前面和后面都是空格,使得它与其它单词分开了,正因为有空格的存在is 才成为了一个单词,所以空格是单词边界, \b 可以匹配到它。把正则表达式改成 /\bis\b/g, 可以看到输出 this IS a dog, 只匹配第二个。 如果只想改变第一个呢?那好办,因为第一个is被包含在一个单词中,所以它的前面不是单词边界,直接改成\B 就可以了, 正则表达式改成 /\Bis\b/g 就可以了.

  ^ 和$ 很好理解, /^T/以大写字母T开头即可, /T$/ 以大写字母T结束即可, 要注意它们的书写位置,一个在前,一个在后. 如果字符串中有换行符, let string = '@123\n@456\n@789', 字符串表现地就像有三行一样. 以下是chrome 浏览器中的输出

这时如果以/^@/g 去进行匹配的话,它只会匹配第一个@,

let reg = /^@/g;
let string = '@123\n@456\n@789'
let replaceString = string.replace(reg,"X");
console.log(replaceString)  
/* 
*    X123
*    @456
*    @789
*/

  如果想匹配三个,那就要用到m修饰符,多行标示符,它表示如果字符串中有换行符,那就把字符串当成多行看待。m 标示符,只有在正则表达式中有^或&时才起作用,这也是把m标示符放到这里说明的原因。

  6 量词

  量词就是表示数量,一个字符出现了多少次。它有以下几种

  +:表示出现一次或多次(至少出现1次),+号吗,越加越多,越来越多,所以是多次。/ab+/, 字符串‘ab’, ‘abb’, ‘abbbbb......’ 都可以和它匹配。

  ? : 表示出现 0次或1次(最多出现1次), ? 表示是不是,是就是1, 不是就是是0, 所以表示0 或1. /ab?/ , 字符串‘a’, ‘ab’ 都可以和它匹配。

  * : 表示出现0,1 或多次, *都是通配符的意思, 通通匹配, 所以出现0次,1次或任意次都可以. /ab*/ , 字符串‘a’, ‘ab’ ,'abb', ‘abbbbb......’  都可以和它匹配。

  {n}:表示出现n次,如/\d{5}/ 表示一个数字要出现5次,如 字符串‘12345’ 可以和它匹配

  {n,m}: 至少出现n次,最多出现m次  /\d{3,5}/ , 字符串‘123’, ‘1234’, ‘12345’ 都可以和它匹配。

  {n, }: 至少出现 n次;  /\d{2,}/   字符串‘12’, ‘123’, ‘12345’ , "12333....." 都可以和它匹配。

  如是在正则表达式中,出现量词,如/\d{3,5}/, ‘123’, ‘1234’, ‘12345’ 都可以和它匹配,而我们的字符串是'123456', 那它怎么匹配,是区配字符串中 的 ‘123’, ‘1234’, 还是‘12345’ ? 这时正则表达式匹配最多出现次数,就是里面的12345, 这也称之为贪婪模式。 

let reg = /\d{3,5}/g;
let string = '123456'
let replaceString = string.replace(reg,"X");
console.log(replaceString)  //X6, 可见它匹配的是12345,最多出现次数

  那怎么样才能让它匹配最小出现次数呢? 就是匹配出现3次,那也好办,就是在量词后面加? 正则表达式改为 /\d{3,5}?/g, 这也称之为非贪婪模式或懒惰模式

let reg = /\d{3,5}?/g;
let string = '123456'
let replaceString = string.replace(reg,"X");
console.log(replaceString)  //XX,123=> X, 456=> X,匹配最少次数

  对于非贪婪模式或贪婪模式,这里还要注意一点,先看一下下面的例子

let reg = /\d{3,5}/g;
let string = '12345678'
let replaceString = string.replace(reg,"X");
console.log(replaceString)  //XX

  上面我们执行的是贪婪模式,它会匹配最多出现的次数,也就是5次,那么结果应该是X678才对,为什么是XX呢? 当贪婪模式匹配字符串的时候,当已经不够最大次数的匹配的时候,会选择更小次数的匹配。比如这里首先匹配12345, 剩下678, 它已经不够最大次数匹配,那就执行更小的次数匹配,那就是3或4,678 正好是3, 所以也就变成了X

  7 分组

  上面我们说过,正则表达式是一个字符一个字符的去匹配,所以如果要匹配一个单词如is ,就是必须写/is/, 如果想要匹配is 出现3次,就只能写/isisis/, 我们想使用量词/is{3}/,但这只表示s出现3次,那怎么修改才能表示is 出现三次,把is 用括号括起来,/(is){3}/. 用括号把is括起来,就表示是它是一个整体,一个组,它们要一起出现,才算匹配成功,所以称之为分组。分组有一个重要的概念,就是引用,当正则表达式中有分组时,我们可以获取到分组的内容,怎么获取,就是$n, n表示数字,$1 表示第一个分组的内容,$2 表示第二个分组的内容,$3 表示第三个分组的内容,依次类推,其实这里还有一个$0, 它比较特殊,所以单列出来,它表示,整个正则表达式匹配成功的内容。 可能不太好理解,写一个例子

写一个时间字符串 '2017-03-05',  正则表达式 /\d{4}-\d{2}-\d{2}/g 可以匹配它,如下,

let reg = /\d{4}-\d{2}-\d{2}/g;
let string = '2017-03-20'
let replaceString = string.replace(reg,"X");
console.log(replaceString)  //X

  这时我们在正则表达式中加上分组,可以看到没有产生影响

let reg = /(\d{4})-(\d{2})-(\d{2})/g;  // 加上分组,就是把三段分别用括号括起来
let string = '2017-03-20'
let replaceString = string.replace(reg,"X");
console.log(replaceString)  //X

  但是有了分组之后,就有引用,我们通过$n可以获取到分组内容,这里有三个分组,可以用$1, $2, $3 分别获取到三个分组内容, 把“X” 分别换成立$1,$2,$3看一个

  把replace 中的 “X” 换成$1, 可以看到输出2017, 表示$1获取的就是第一个分组 (\d{4}) 的内容

let reg = /(\d{4})-(\d{2})-(\d{2})/g;  // 加上分组
let string = '2017-03-20'
let replaceString = string.replace(reg,"$1");
console.log(replaceString)  //2017

  把replace 中的 “X” 换成$2, 输出03, 表示$2获取的就是第二个分组 (\d{2}) 的内容, $3 可以自己试一下。

let reg = /(\d{4})-(\d{2})-(\d{2})/g; 
let string = '2017-03-20'
let replaceString = string.replace(reg,"$2"); // $2
console.log(replaceString)  //03

  $1, $2,$3都是字符串,可以进行任意组合,我们就可以得到想要的结果, '$2/$3/$1', 我们就可以把一种日期格式,转化成另外一种日期格式

let reg = /(\d{4})-(\d{2})-(\d{2})/g; 
let string = '2017-03-20'
let replaceString = string.replace(reg,"$2/$3/$1"); 
console.log(replaceString)  //  03/20/2017

  忽略分组:$n获取分组的内容和正则表达式中的分组是一一对应的,正则表达式中有几个分组,它从左向右就会对应几个$n, $1 永远获取的是第一个分组内容,$2 永远获取的都是第二个分组的内容,但有时候,我们想跳过某个分组,获取它下一个分组,比如$2 获取第三个分组的内容,这时正则表达式中的第二个分组前面要加 ?:, 表示获取内容的时候可以忽略这个分组

let reg = /(\d{4})-(?:\d{2})-(\d{2})/g; 
let string = '2017-03-20'
let replaceString = string.replace(reg,'$2'); // $2
console.log(replaceString)  //20

  在上面的代码中,我们在第二个分组前面加了 ?:进行了忽略了,所以$2 获取的是第三个分组的内容。

  分组还有一个概念,就是重复子项,它用\1,\2来表示,它们只用在正则表达式中, \1 代表的也是第一个分组,\2代表的是第二个分组,它们主要的作用是匹配以下这种字符串,

、121, 222, 323, 424, 第一个数字和第三个数字相等,但又是不确定的数字, 所以在书写正则表达式时,必须保证第一项和第三项相等,第三项是第一项的复制,\1, 就是正则表达式中第一个分组的复制。

let reg = /(\d)2\1/g; 
let string = '121 222 323 424'
let replaceString = string.replace(reg,'X');
console.log(replaceString)  // X X X X

  还有一个或的概念,符号表示为|, /ab|ac/, 当它们去匹配字符串时,只要出现其中的一个就算成功

 

转载于:https://www.cnblogs.com/SamWeb/p/6653994.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值