正則表達式迷你書-筆記

API 使用javascript

String#search
  String#split
  String#match
  String#replace
  RegExp#test
  RegExp#exec

看完你就會正則表達式了
四種操做java

  • 驗證
  • 切分
  • 提取
  • 替換

test search match exec正則表達式

第一章 正則表達式字符匹配攻略

正則表達式是匹配模式,要麼匹配字符,要麼匹配位置編程

  • {m,n} 至少m,至多n
  • [a-z] 匹配a-z中的任一個字符 --範圍表示法

若是要匹配a - z 則[-az] [az-] [a\-z]segmentfault

  • [abc] 要麼a要麼b要麼c
\d === [0-9]
\D === [^0-9]
\w === [0-9a-zA-Z_]
\W === [^0-9a-zA-Z_]
\s === [ \t\v\n\r\f]
. 通配符,表示幾乎任意字符
{m} 表示出現m次

要匹配任意字符 可使用
[dD] [wW] [sS] [^] 中的任意一個函數

貪婪匹配
惰性匹配 ?測試

var regex = /\d{2,5}?/g
var string = "123 3456 1290 13498"
console.log(string.match(regex))

//  當兩個足夠的時候就不在往下匹配了
["12", "34", "56", "12", "90", "13", "49"]

貪婪量詞es5

{m,n}
{m,}
?
+
*

惰性量詞 在貪婪量詞後面加上?就行spa

多選分支 | 也是惰性的code

var regex = /good|goodbye/g
var string = "goodbye"
console.log(string.mathc(regex)) // good 
匹配到一個了,後面的就再也不嘗試了

匹配16進制顏色值

var regex = /#([0-9A-Fa-f])|(0-9A-Fa-f){3}/g

匹配時間

var regex = /^([01][0-9]|[2][0-3]) : [0-5][0-9]$/
console.log(regex.test("23:59")) //true

若是要求匹配 7:9 前面的0能夠省略

var regex = /^(0?[0-9]|1[0-9]|[2][0-3]):(0?[0-9]|[1-5][0-9])$/;

匹配年月日

year [0-9]{4}
month (0[1-9]|1[0-2])  12個月
day 最大31  (0[1-9]|[12][0-9]|3[01])  01 02...09 10,11....20,21....30,31

var regex = /^[0-9]{4}-(0[1-9]|1[0-2])-(0[1-9]|[12][0-9]|3[01])$/;
 console.log( regex.test("2017-06-10") ); //true

匹配id

var regex = /id=".*"/
 var string = '<div id="container" class="main"></div>';
 console.log(string.match(regex)[0]);
 // => id="container" class="main"
 
 由於 . 是通配符,自己就匹配雙引號的,而量詞 * 又是貪婪的,當遇到 container 後面雙引號時,是不會 停下來,會繼續匹配,直到遇到最後一個雙引號爲止。
解決之道,可使用惰性匹配:
 var regex = /id=".*?"/
 var string = '<div id="container" class="main"></div>';
 console.log(string.match(regex)[0]);
 // => id="container"

第二章 正則表達式位置匹配攻略

  • 如何匹配位置暱?

在es5中,共有6個錨
^ $ b B (?=p) (?!p)

  • 多行匹配模式(即有修飾符 m)時,兩者是行的概念,這一點須要咱們注意:

    \n 換行
    var result = "I\nlove\njavascript".replace(/^|$/gm, '#');
    console.log(result);
    /*
    #I#
    #love#
    #javascript#
    */
  • b 是單詞變界 具體是w 與W之間的位置 w與^ w與$之間的位置

    var result = "[JS] Lesson_01.mp4".replace(/\b/g, '#');
     console.log(result);
     // => "[#JS#] #Lesson_01#.#mp4#"
  • B : w 與 w、 W 與 W、^ 與 W,W 與 $ 之間的位置

    var result = "[JS] Lesson_01.mp4".replace(/\B/g, '#');
     console.log(result);
     // => "#[J#S]# L#e#s#s#o#n#_#0#1.m#p#4"

(?=p) p是一個子模式,即p前面的位置,或者說,該位置後面的字符要匹配p

var result = "hello".replace(/(?=l)/g, '#');
 console.log(result);
 // => "he#l#lo"

(?!p)
而 (?!p) 就是 (?=p) 的反面意思,好比:

var result = "hello".replace(/(?!l)/g, '#');
 console.log(result);
 // => "#h#ell#o#"

把位置理解空字符

千位分隔符

var regex = /(?!^)(?=(\d{3})+$)/g
var result = '1234567'.replace(regex, ',')

若是要把 "12345678 123456789" 替換成 "12,345,678 123,456,789"。
此時咱們須要修改正則,把裏面的開頭 ^ 和結尾

$,修改爲 \b: var string = "12345678 123456789",
  regex = /(?!\b)(?=(\d{3})+\b)/g;
  var result = string.replace(regex, ',')
  console.log(result);
  // => "12,345,678 123,456,789"

(?!b) == B

貨幣案例

function format (num) {
    return num.toFixed(2).replace(/\B(?=(\d{3})+\b)/g, ",").replace(/^/, "$ ");
};
console.log( format(1888) );
// => "$ 1,888.00"

第三章 分組和分支結構

() |

  • 分組引用

分組能夠捕獲數據
-分組引用
替換

var regex = /(\d{4})-(\d{2})-(\d{2})/;
  var string = "2017-06-12";
  var result = string.replace(regex, "$2/$3/$1");
  console.log(result);
  // => "06/12/2017"
  
  // 其中 replace 中的,第二個參數裏用 $一、$二、$3 指代相應的分組。等價於以下的形式:
  var regex = /(\d{4})-(\d{2})-(\d{2})/;
  var string = "2017-06-12";
  var result = string.replace(regex, function () {
      return RegExp.$2 + "/" + RegExp.$3 + "/" + RegExp.$1;
  });
  console.log(result);
  // => "06/12/2017"

也等價於:
  var regex = /(\d{4})-(\d{2})-(\d{2})/;
  var string = "2017-06-12";
  var result = string.replace(regex, function (match, year, month, day) {
      return month + "/" + day + "/" + year;
  });
  console.log(result);
  // => "06/12/2017"

-反向引用 -- 引用以前出現的分組

regex.test(string)
regex.exec(string)
string.match(regex)
RegExp.$1

var regex = /\d{4}(-|\/|\.)\d{2}\1\d{2}/;
  var string1 = "2017-06-12";
  var string2 = "2017/06/12";
  var string3 = "2017.06.12";
  var string4 = "2016-06/12";
  console.log( regex.test(string1) ); // true
  console.log( regex.test(string2) ); // true
  console.log( regex.test(string3) ); // true
  console.log( regex.test(string4) ); // false
\1 表示前面引用的那個分組 無論前面這個分組好比(-|\/|\.)匹配到什麼 好比- \1都匹配那個一樣的具體某個字符

 \2 \3表示指代第二個和第三個分組

tips 10 表示第10個分組
那麼要匹配1 和0 的話,(?:1)0 1(?:0)

反向引用 是引用前面的分組,可是若是正則裏面引用了不存在的分組時,只是匹配了反向引用的字符自己

分組後面有量詞會怎麼樣?

分組後面有量詞的話,分組最終捕獲到的數據是最後一次的匹配

var regex = /(\d)+/;
  var string = "12345";
  console.log( string.match(regex) );
  // => ["12345", "5", index: 0, input: "12345"]
從上面看出,分組 (\d) 捕獲的數據是 "5"。 

同理對於反向引用,也是這樣的。測試以下:
  var regex = /(\d)+ \1/;
  console.log( regex.test("12345 1") );
  // => false
  console.log( regex.test("12345 5") );
  // => true
  • 非捕獲括號 (?:p) (?:p1|p2|p3)

若是隻想要括號最原始的功能,但不會引用它,即,既不在API裏引用,也不在正則裏反向引用,此時可使用非捕獲括號(?:p) 和 (?:p1|p2|p3)

var regex = /(?:ab)+/g;
  var string = "ababa abbb ababab";
  console.log( string.match(regex) );
  // => ["abab", "ab", "ababab"]
同理,第二例子能夠修改成:
  var regex = /^I love (?:JavaScript|Regular Expression)$/;
  console.log( regex.test("I love JavaScript") );
  console.log( regex.test("I love Regular Expression") );
  // => true
// => true

捕獲與非捕獲括號區別

var str = "a1***ab1cd2***c2";
var reg1 = /((ab)+\d+)((cd)+\d+)/i;
var reg2 = /((?:ab)+\d+)((?:cd)+\d+)/i;
alert(str.match(reg1));//ab1cd2,ab1,ab,cd2,cd
alert(str.match(reg2));//ab1cd2,ab1,cd2

//能夠看出捕獲分組和非捕獲分組的區別了吧:非捕獲分組,只是用來匹配,並不會提取分組內容。也就是說,若是咱們只想用圓括號將一些字符用數量詞修飾,並不須要這個分組的內容,這就是非捕獲分組
replace 用法
語法: stringObj.replace(regexp/substr,replacement)

NO.5 第一個參數是正則且有子表達式,第二個參數函數且帶有多個參數
var str5 = '這是一段原始文本,須要替換的內容"3c這要替換4d"!';

var newStr = str5.replace( /([0-9])([a-z])/g,function (arg1,arg2,arg3,arg4,arg5){
 console.log( arg1 );
  console.log( arg2 );
  console.log( arg3 );
  console.log( arg4 );
  console.log( arg5 );
} );
//輸出:
3c
3
c
17
這是一段原始文本,須要替換的內容"3c這要替換4d"!
4d
4
d
23
這是一段原始文本,須要替換的內容"3c這要替換4d"!
上面的例子第一個參數arg1表示匹配的總體,arg2表示第一個子表達式,arg3表示第二個子表達式,接下來的參數arg4是一個整數,聲明瞭表示子匹配在 stringObject 中出現的位置。最後一個參數是 stringObject 自己。

NO.3 第一個參數是正則,第二個參數是帶$符的字符串

var str3 = '這是一段原始文本,"3c這要替換4d"!';
var newStr = str3.replace( /([0-9])([a-z])/g,"$1" );
console.log( newStr );  //輸出:    這是一段原始文本,"3這要替換4"!';

var newStr = str3.replace( /([0-9])([a-z])/g,"$2" ); // 這是一段原始文本,」c這要替換d」!';

cankao
案例

駝峯轉換

若是不加? 會多匹配一個空格 加問號後,由於? 是懶得匹配,因此不會匹配最後一個空格
image

function camelize (str) {
      return str.replace(/[-_\s]+(.)?/g, function (match, c) { console.log(c,'c')
          return c ? c.toUpperCase() : '';
      });
  }
  console.log( camelize('-moz-transform  ') );
<!--VM2177:2 m c-->
<!--VM2177:2 t c-->
<!--VM2177:2 undefined "c"-->
<!--VM2177:6 MozTransform-->
其中分組 (.) 表示首字母。單詞的界定是,前面的字符能夠是多個連字符、下劃線以及空白符。正則後面
的 ? 的目的,是爲了應對 str 尾部的字符可能不是單詞字符,好比 str 是 '-moz-transform '

第五章 正則表達式的拆分
匹配字符串
好比匹配 "[abc]" 和 "{3,5}"

var string = "[abc]"
var regex = /\[abc]/g
console.log(string.macth(regex)[0])

在第一個方括號轉義便可 由於後面的方括號構不成字符組

var string = "JavaScript";
  console.log( string.match(/.{4}(.+)/)[1] );
  // => Script
  // 前面的點出現四次 後面匹配的點出現一次以上

密碼匹配問題: 要求密碼長度 6-12 位,由數字、小寫字符和大寫字母組成,但必須至少包括 2 種字

var regex1 = /^[0-9A-Za-z]{6,12}$/;
 var regex2 = /^[0-9]{6,12}$/;
 var regex3 = /^[A-Z]{6,12}$/;
 var regex4 = /^[a-z]{6,12}$/;
 function checkPassword (string) {
     if (!regex1.test(string)) return false;
     if (regex2.test(string)) return false;
     if (regex3.test(string)) return false;
     if (regex4.test(string)) return false;
     return true;
}

匹配浮點數
符號 [+-]
整數部分 d+
小數部分 .d+

匹配 1.23 +1.23 -1.23 10 +10 -10 .2 +.2 -.2

/^[+-]?(\d\.\d+|\d+|\.\d+)$/

第七章節 正則表達式編程

  1. 正則表達式的四種操縱

驗證 切分 提取 替換

相關文章
相關標籤/搜索