>  기사  >  웹 프론트엔드  >  누구나 알고 있는 JavaScript 정규식에 대한 자세한 설명

누구나 알고 있는 JavaScript 정규식에 대한 자세한 설명

黄舟
黄舟원래의
2017-03-14 15:06:351258검색

이것이 정규 표현의 요약이라면 매뉴얼로 보는 편이 낫다.

RegExp의 세 가지 주요 방법

이 기사의 RegExp는 직접 수량 구문인 /pattern/attributes를 사용합니다. 속성에는 i, m, g 세 가지 옵션이 있습니다. m(다중 줄 일치)은 일반적으로 사용되지 않으며 직접 생략할 수 있으므로 패턴(일치 패턴)은 다음과 같이 표현할 수 있습니다. i(무시)는 대소문자를 구분하지 않음을 의미합니다(로컬

검색

일치). 이는 상대적으로 간단하며 다음 예에서는 설명되지 않습니다. g(글로벌)는 전역(일치 검색)을 의미합니다. , 하나를 찾은 후 계속 검색하십시오. 이는 상대적으로 복잡합니다. 특히 다음 방법을 소개합니다. RegExp의 3대 메소드이므로 모두 Pattern.test/exec/complie 형식으로 되어있습니다.

    test
  • 주요 기능: 지정된
문자열

에 특정 하위 문자열(또는 일치하는 패턴)이 포함되어 있는지 감지하고 반환합니다. 참 또는 거짓. 예는 다음과 같습니다.

var pattern = /hello/ig;

속성이 g를 사용하는 경우 계속 검색할 수 있으며, 이는 lastIndex

속성

도 포함됩니다(g 소개 참조). 실행).

    exec
  • 주요 함수: 지정된 문자열에서 필요한 하위 문자열(또는 일치하는 패턴)을 추출하고
배열 일치하는 결과를 저장하고, 결과가 없으면

null이 반환됩니다. (전체 또는 지정된 인덱스 데이터를 추출하기 위해 를 반복하는 자신만의 메서드 를 작성할 수도 있습니다.) exec는 탐지할 수 있을 뿐만 아니라, 또한 탐지 후 결과를 직접 추출합니다.

예는 다음과 같습니다.

var s = 'you love me and I love you';
var pattern = /you/;
var ans = pattern.test(s);
console.log(ans); // true

출력이 매우 흥미롭습니다. 이 배열의 0번째 요소는 정규식과 일치하는 텍스트이고, 첫 번째 요소는 RegExp

Object

(있는 경우)의 첫 번째 하위 표현식과 일치하는 텍스트이며, 두 번째 요소는 RegExpObject(있는 경우)의 두 번째 하위 표현식 등입니다.

"하위 표현식과 일치하는 텍스트"란 무엇입니까? 다음 예를 보세요:

var s = 'you love me and I love you';
var pattern = /you/;
var ans = pattern.exec(s);
console.log(ans); // ["you", index: 0, input: "you love me and I love you"]
console.log(ans.index); // 0
console.log(ans.input); // you love me and I love you

소위 하위 표현식은 패턴에서 () 안에 있는 것입니다(자세한 내용은 아래 하위 표현식 소개를 참조하세요). 위 예시의 배열 길이를 보면 2 입니다! ! index와 input은 배열 속성일 뿐입니다(

chr

ome의 위 출력은 오해의 소지가 있을 수 있음).

exec() 메서드는 배열 요소와 길이 속성 외에도 두 가지 속성을 반환합니다. index 속성은 일치하는 텍스트의 첫 번째 문자 위치를 선언합니다. 입력 속성은 검색된 문자열 string

을 저장합니다.

가 비전역 RegExp 객체 의 exec() 메서드를 호출할 때 반환된 배열은 String.match() 메서드를 호출하여 반환된 배열과 동일하다는 것을 알 수 있습니다. . "g" 매개변수를 사용하는 경우 exec()는 다음과 같이 작동합니다(여전히 위의 예 ps: 테스트에서 g 매개변수를 사용하는 경우에도 비슷합니다).

첫 번째 "당신"을 찾아서 그 위치를 저장
  1. 다시 exec()를 실행하면 저장된 위치(lastIndex)부터 검색을 시작하고 다음 "당신"을 찾아 저장합니다. 위치
  2. RegExpObject가 전역 정규 표현식인 경우 exec()의
  3. 동작
은 약간 더 복잡합니다. RegExpObject의 lastIndex 속성에 지정된 문자에서 문자열 검색을 시작합니다. exec()는 표현식과 일치하는 텍스트를 찾으면 RegExpObject의 lastIndex 속성을 일치 후 일치하는 텍스트의 마지막 문자 옆 위치로 설정합니다. 이는 exec() 메서드를 반복적으로 호출하여 문자열에서 일치하는 모든 텍스트를 반복할 수 있음을 의미합니다. exec()가 더 이상 일치하는 텍스트를 찾지 못하면 null을 반환하고 lastIndex 속성을 0으로 재설정합니다. 여기에는 g 및 test(또는 g 및 exec)와 결합된 경우에만 작동하는 lastIndex 속성이 도입되었습니다. 패턴의 속성인

정수로, 다음 매칭이 시작되는 문자 위치를 나타냅니다. 예제는 다음과 같습니다.

var s = 'you love me and I love you';
var pattern = /y(o?)u/;
var ans = pattern.exec(s);
console.log(ans);   // ["you", "o", index: 0, input: "you love me and I love you"]
console.log(ans.length) // 2

결과는 다음과 같습니다.

이해하기 쉬울 것입니다. 세 번째로 " you"를 반복하므로 null이 반환되고 lastIndex 값도 0이 됩니다.

如果在一个字符串中完成了一次模式匹配之后要开始检索新的字符串(仍然使用旧的pattern),就必须手动地把 lastIndex 属性重置为 0。

  • compile

主要功能:改变当前匹配模式(pattern)

这货是改变匹配模式时用的,用处不大,略过。详见JavaScript compile() 方法

String 四大护法

和RegExp三大方法分庭抗礼的是String的四大护法,四大护法有些和RegExp三大方法类似,有的更胜一筹。

既然是String家族下的四大护法,所以肯定是string在前,即str.search/match/replace/split形式。

既然是String的方法,当然参数可以只用字符串而不用pattern。

  • search

主要功能:搜索指定字符串中是否含有某子串(或者匹配模式),如有,返回子串在原串中的初始位置,如没有,返回-1。

是不是和test类似呢?test只能判断有木有,search还能返回位置!当然test()如果有需要能继续找下去,而search则会自动忽略g(如果有的话)。实例如下:

var s = 'you love me and I love you';
var pattern = /you/;
var ans = s.search(pattern);
console.log(ans);  // 0

话说和String的indexOf方法有点相似,不同的是indexOf方法可以从指定位置开始查找,但是不支持正则。

  • match

主要功能:和exec类似,从指定字符串中查找子串或者匹配模式,找到返回数组,没找到返回null

match是exec的轻量版,当不使用全局模式匹配时,match和exec返回结果一致;当使用全局模式匹配时,match直接返回一个字符串数组,获得的信息远没有exec多,但是使用方式简单。

实例如下:

var s = 'you love me and I love you';
console.log(s.match(/you/));    // ["you", index: 0, input: "you love me and I love you"]
console.log(s.match(/you/g));   // ["you", "you"]
  • replace

主要功能:用另一个子串替换指定字符串中的某子串(或者匹配模式),返回替换后的新的字符串  str.replace(‘搜索模式’,'替换的内容’)  如果用的是pattern并且带g,则全部替换;否则替换第一处。

实例如下:

var s = 'you love me and I love you';
console.log(s.replace('you', 'zichi')); // zichi love me and I love you
console.log(s.replace(/you/, 'zichi')); // zichi love me and I love you
console.log(s.replace(/you/g, 'zichi'));    // zichi love me and I love zichi

如果需要替代的内容不是指定的字符串,而是跟匹配模式或者原字符串有关,那么就要用到$了(记住这些和$符号有关的东东只和replace有关哦)。

怎么用?看个例子就明白了。

var s = 'I love you';
var pattern = /love/;
var ans = s.replace(pattern, '$`' + '$&' + "$'");
console.log(ans); // I I love you you

没错,’$`’ + ‘$&’ + “$’”其实就相当于原串了!

replace的第二个参数还能是函数,看具体例子前先看一段介绍:

注意:第一个参数是匹配到的子串,接下去是子表达式匹配的值,如果要用子表达式参数,则必须要有第一个参数(表示匹配到的串),也就是说,如果要用第n个参数代表的值,则左边参数都必须写出来。最后两个参数跟exec后返回的数组的两个属性差不多。

var s = 'I love you';
var pattern = /love/;
var ans = s.replace(pattern, function(a) {  // 只有一个参数,默认为匹配到的串(如还有参数,则按序表示子表达式和其他两个参数)
  return a.toUpperCase();
});
console.log(ans); // I LOVE you
  • split

主要功能:分割字符串

字符串分割成字符串数组的方法(另有数组变成字符串的join方法)。直接看以下例子:

var s = 'you love me and I love you';
var pattern = 'and';
var ans = s.split(pattern);
console.log(ans);   // ["you love me ", " I love you"]

如果你嫌得到的数组会过于庞大,也可以自己定义数组大小,加个参数即可:

var s = 'you love me and I love you';
var pattern = /and/;
var ans = s.split(pattern, 1);
console.log(ans);   // ["you love me "]

RegExp 字符

  • \s 任意空白字符 \S相反 空白字符可以是: 空格符 (space character) 制表符 (tab character) 回车符 (carriage return character) 换行符 (new line character) 垂直换行符 (vertical tab character) 换页符 (form feed character)

  • \b是正则表达式规定的一个特殊代码,代表着单词的开头或结尾,也就是单词的分界处。虽然通常英文的单词是由空格,标点符号或者换行来分隔的,但是\b并不匹配这些单词分隔字符中的任何一个,它只匹配一个位置。(和^ $ 以及零宽断言类似)

  • \w 匹配字母或数字或下划线   [a-z0-9A-Z_]完全等同于\w

贪婪匹配和懒惰匹配

什么是贪婪匹配?贪婪匹配就是在正则表达式的匹配过程中,默认会使得匹配长度越大越好。

var s = 'hello world welcome to my world';
var pattern = /hello.*world/;
var ans = pattern.exec(s);
console.log(ans)  // ["hello world welcome to my world", index: 0, input: "hello world welcome to my world"]

以上例子不会匹配最前面的Hello World,而是一直贪心的往后匹配。

那么我需要最短的匹配怎么办?很简单,加个‘?’即可,这就是传说中的懒惰匹配,即匹配到了,就不往后找了。

var s = 'hello world welcome to my world';
var pattern = /hello.*?world/;
var ans = pattern.exec(s);
console.log(ans)  // ["hello world", index: 0, input: "hello world welcome to my world"]

懒惰限定符(?)添加的场景如下:

子表达式

  • 表示方式

用一个小括号指定:

var s = 'hello world';
var pattern = /(hello)/;
var ans = pattern.exec(s);
console.log(ans);
  • 子表达式出现场景

在exec中数组输出子表达式所匹配的值:

var s = 'hello world';
var pattern = /(h(e)llo)/;
var ans = pattern.exec(s);
console.log(ans); // ["hello", "hello", "e", index: 0, input: "hello world"]

在replace中作为替换值引用

var s = 'hello world';
var pattern = /(h\w*o)\s*(w\w*d)/;
var ans = s.replace(pattern, '$2 $1')
console.log(ans); // world hello

后向引用 & 零宽断言

  • 子表达式的序号问题

简单地说:从左向右,以分组的左括号为标志,第一个出现的分组的组号为1,第二个为2,以此类推。

复杂地说:分组0对应整个正则表达式实际上组号分配过程是要从左向右扫描两遍的:第一遍只给未命名组分配,第二遍只给命名组分配--因此所有命名组的组号都大于未命名的组号。可以使用(?:exp)这样的语法来剥夺一个分组对组号分配的参与权.

后向引用

如果我们要找连续两个一样的字符,比如要找两个连续的c,可以这样/c{2}/,如果要找两个连续的单词hello,可以这样/(hello){2}/,但是要在一个字符串中找连续两个相同的任意单词呢,比如一个字符串hellohellochinaworldworld,我要找的是hello和world,怎么找?

这时候就要用后向引用。看具体例子:

var s = 'hellohellochinaworldworld';
var pattern = /(\w+)\1/g;
var a = s.match(pattern);
console.log(a); // ["hellohello", "worldworld"]

这里的\1就表示和匹配模式中的第一个子表达式(分组)一样的内容,\2表示和第二个子表达式(如果有的话)一样的内容,\3 \4 以此类推。(也可以自己命名,详见参考文献)

或许你觉得数组里两个hello两个world太多了,我只要一个就够了,就又要用到子表达式了。因为match方法里是不能引用子表达式的值的,我们回顾下哪些方法是可以的?没错,exec和replace是可以的!

exec方式:

var s = 'hellohellochinaworldworld';
var pattern = /(\w+)\1/g;
var ans;
do {
  ans = pattern.exec(s);
  console.log(ans);
} while(ans !== null);

// result
// ["hellohello", "hello", index: 0, input: "hellohellochinaworldworld"] index.html:69
// ["worldworld", "world", index: 15, input: "hellohellochinaworldworld"] index.html:69
// null

如果输出只要hello和world,console.log(ans[1])即可。

replace方式:

var s = 'hellohellochinaworldworld';
var pattern = /(\w+)\1/g;
var ans = [];
s.replace(pattern, function(a, b) {
 ans.push(b);
});
console.log(ans);   // ["hello", "world"]

如果要找连续n个相同的串,比如说要找出一个字符串中出现最多的字符:

String.prototype.getMost = function() {
  var a = this.split('');
  a.sort();
  var s = a.join('');
  var pattern = /(\w)\1*/g;
  var a = s.match(pattern);
  a.sort(function(a, b) {
    return a.length < b.length;
  });
  var letter = a[0][0];
  var num = a[0].length;
  return letter + &#39;: &#39; + num;
}

var s = &#39;aaabbbcccaaabbbcccccc&#39;;
console.log(s.getMost()); // c: 9

如果需要引用某个子表达式(分组),请认准后向引用!

零宽断言

别被名词吓坏了,其实解释很简单。

它们用于查找在某些内容(但并不包括这些内容)之后的东西,也就是说它们像\b,^,$那样用于指定一个位置,这个位置应该满足一定的条件(即断言)

  • (?=exp)

零宽度正预测先行断言,它断言自身出现的位置的后面能匹配表达式exp。

// 获取字符串中以ing结尾的单词的前半部分
var s = &#39;I love dancing but he likes singing&#39;;
var pattern = /\b\w+(?=ing\b)/g;
var ans = s.match(pattern);
console.log(ans); // ["danc", "sing"]
  • (?!exp)

零宽度负预测先行断言,断言此位置的后面不能匹配表达式exp

// 获取第五位不是i的单词的前四位
var s = &#39;I love dancing but he likes singing&#39;;
var pattern = /\b\w{4}(?!i)/g;
var ans = s.match(pattern);
console.log(ans); // ["love", "like"]

javascript正则只支持前瞻,不支持后瞻((?<=exp)和(?

关于零宽断言的具体应用可以参考综合应用一节给字符串加千分符。

其他

  • 字符转义

因为某些字符已经被正则表达式用掉了,比如. * ( ) / \  [],所以需要使用它们(作为字符)时,需要用\转义

var s = &#39;http://www.cnblogs.com/zichi/&#39;;
var pattern = /http:\/\/www\.cnblogs\.com\/zichi\//;
var ans = pattern.exec(s);
console.log(ans); // ["http://www.cnblogs.com/zichi/", index: 0, input: "http://www.cnblogs.com/zichi/"]
  • 分支条件

如果需要匹配abc里的任意字母,可以用[abc],但是如果不是单个字母那么简单,就要用到分支条件。

分支条件很简单,就是用|表示符合其中任意一种规则。

var s = "I don&#39;t like you but I love you";
var pattern = /I.*(like|love).*you/g;
var ans = s.match(pattern);
console.log(ans); // ["I don&#39;t like you but I love you"]

答案执行了贪婪匹配,如果需要懒惰匹配,则:

var s = "I don&#39;t like you but I love you";
var pattern = /I.*?(like|love).*?you/g;
var ans = s.match(pattern);
console.log(ans); // ["I don&#39;t like you", "I love you"]

综合应用

  •  去除字符串首尾空格(replace)

String.prototype.trim = function() {
  return this.replace(/(^\s*)|(\s*$)/g, "");
};
var s = &#39;    hello  world     &#39;;
var ans = s.trim();
console.log(ans.length);    // 12
  • 给字符串加千分符(零宽断言)

String.prototype.getAns = function() {
  var pattern = /(?=((?!\b)\d{3})+$)/g;
  return this.replace(pattern, &#39;,&#39;);
}

var s = &#39;123456789&#39;;
console.log(s.getAns());  // 123,456,789
  • 找出字符串中出现最多的字符(后向引用)

String.prototype.getMost = function() {
  var a = this.split(&#39;&#39;);
  a.sort();
  var s = a.join(&#39;&#39;);
  var pattern = /(\w)\1*/g;
  var a = s.match(pattern);
  a.sort(function(a, b) {
    return a.length < b.length;
  });
  var letter = a[0][0];
  var num = a[0].length;
  return letter + &#39;: &#39; + num;
}

var s = &#39;aaabbbcccaaabbbcccccc&#39;;
console.log(s.getMost()); // c: 9

常用匹配模式(持续更新

  1.  只能输入汉字:/^[\u4e00-\u9fa5]{0,}$/

요약

  1. test: 지정된 문자열에 특정 하위 문자열(또는 일치하는 패턴)이 있는지 확인하고 true를 반환합니다. 또는 false, 필요한 경우 전역 패턴 검색을 수행할 수 있습니다.

  2. exec: 지정된 문자열에 특정 하위 문자열(또는 일치하는 패턴)이 있는지 확인하고, 있으면 배열을 반환합니다(배열 정보가 풍부하고, 위의 소개를 참조하세요. null이 반환되지 않으면 필요한 경우 전역 검색을 수행하여 모든 하위 문자열(또는 일치하는 패턴) 정보를 찾을 수 있습니다. 일치하는 패턴의 하위 표현식입니다.

  3. 컴파일

    : 정규식에서 패턴 수정

  4. 검색

    : 지정된 내용 확인 문자 문자열에 특정 하위 문자열(또는 일치하는 패턴)이 있습니까? 그렇다면 원래 문자열에서 하위 문자열(또는 일치하는 패턴)의 시작 위치를 반환합니다. 그렇지 않으면 -1을 반환합니다. 글로벌 검색이 불가능합니다.

  5. 일치

    : 지정된 문자열에 특정 하위 문자열(또는 일치하는 패턴)이 있는지 확인합니다. 비전역 모드에서 반환된 정보가 exec와 일치합니다. ; 전역 검색을 수행하는 경우 문자열 배열을 직접 반환합니다. (각 일치 항목에 대한 추가 정보가 필요하지 않은 경우 exec 대신 match를 사용하는 것이 좋습니다)

  6. replace

    : 특정 하위 문자열이 있는지 확인 지정된 문자열(또는 일치하는 패턴)에서 이를 다른 하위 문자열로 바꿉니다(하위 문자열은 원래 문자열 또는 검색된 하위 문자열과 관련될 수 있음). g가 활성화되면 전체적으로 대체되고, 그렇지 않으면 첫 번째 문자열만 대체됩니다. 교체되었습니다. replace 메소드는 하위 표현식에 해당하는 값을 참조할 수 있습니다.

  7. split

    : 특정 패턴을 사용하여 문자열을 분할하고 Array의 조인 방법과 정반대로 문자열 배열을 반환합니다.

  8. 하위 표현식

    : 역참조를 사용하여 참조할 수 있는 괄호로 묶인 정규 일치 표현식입니다. exec로 가져오거나 실제 일치 값을 바꿀 수도 있습니다. .

  9. 역방향 참조

    : 하위 표현식이 위치한 그룹을 참조합니다.

  10. 폭이 0인 어설션

    : b ^ 및 $와 유사한 위치 개념입니다.

위 내용은 누구나 알고 있는 JavaScript 정규식에 대한 자세한 설명의 상세 내용입니다. 자세한 내용은 PHP 중국어 웹사이트의 기타 관련 기사를 참조하세요!

성명:
본 글의 내용은 네티즌들의 자발적인 기여로 작성되었으며, 저작권은 원저작자에게 있습니다. 본 사이트는 이에 상응하는 법적 책임을 지지 않습니다. 표절이나 침해가 의심되는 콘텐츠를 발견한 경우 admin@php.cn으로 문의하세요.