淺嘗正規表示式

Mopecat發表於2018-03-03

之前寫正則都是各種上網搜尋,還是沒有系統的學習過正規表示式的用法,今天稍稍研究了一下下,感覺還是收穫頗豐的,分享給各位,希望對於你們有所幫助~~


修飾符

  • g --全域性匹配
  • i --不區分大小寫,預設區分
  • m --多行搜尋

預定義類字元

  • \d: 數字;[0-9]
  • \D: 非數字字元;[^0-9]
  • \s: 空白符;[\t\n\x0B\f\r]
  • \S: 非空白符;[^\t\n\x0B\f\r]
  • \w: 單詞字元(字母,數字,下劃線);[a-zA-Z_0-9]
  • \W: 非單詞字元;[^a-zA-Z_0-9]

字元類

  • []: 表示字元類 []中的^表示取反,-表示範圍如:[0-9][a-z];

量詞

  • ?: 出現0次或者1次(最多出現一次);
  • +: 出現1次或者多次(最少出現1次);
  • *: 出現0次或者多次(任意次);
  • {n}: 出現n次;
  • {n,m}: 出現n到m次
  • {n,}: 至少出現n次;

常用的邊界字元

  • ^: 以xxxx開始;
  • $: 以xxxx結尾;
  • \b: 單詞邊界;
  • \B: 非單詞邊界;

貪婪模式

\d{3,6}匹配3-6個數字,那麼 "12345678"就會匹配\d{6}

非貪婪模式

在量詞後面加上?就會盡可能少的匹配了,上面的例子\d{3,6}? 就會匹配\d{3}

分組

想要匹配abc重複三次的場景,abc{3}不就行了?事實上abc{3}匹配的是c{3},若想匹配abc3次則需要用到分組的概念了;
正則中()表示分組,及(abc){3}為匹配 abc 3次 $n代表匹配的分組
如:2018-03-03匹配換成2018年03月03日?

"2018-03-01".replace(/(\d{4})-(\d{2})-(\d{2})/g,"$1$2$3日");
複製程式碼

分組中不想被匹配到的分組在分組中加上?:就可以了,如上例:

"2018-03-01".replace(/(\d{4})-(?:\d{2})-(\d{2})/g,"$1$2$3日");
複製程式碼

這時第二個分組就不會被捕獲,就相當於有兩個分組,所以不存在$3這時的輸出結果就會是 "2018年01月$3日";

aaa | bbb 兩個同時匹配

前瞻,後顧

前瞻就是在正規表示式匹配到規則的時候,向前檢查是否符合斷言("前"的概念就是正規表示式從文字頭部向尾部開始解析)
Javascript 不支援後顧所以這裡就不做過多研究了哈。 -符合特定斷言為 肯定/正向 匹配 正向前瞻:exp(?=assert) 例子:

"s3&df34a7".replace(/\w(?=\d)/g,'OK');
複製程式碼

會輸出 "OK3&dOKOK4OK7"即找到匹配的單詞(\w)後會再次匹配後面的字元是不是數字,如果是則當前匹配的字元替換為OK,本次替換的單詞(\w)是s,f,3,a

-不符合特定斷言為 否定/負向 匹配 負向前瞻:exp(?!assert) 栗子:

"s3&df34a7".replace(/\w(?=\d)/g,'OK');
複製程式碼

會輸出 "sOK&OKf3OKaOK"即找到匹配的單詞(\w)後會再次匹配後面的字元是不是數字,如果不是則當前匹配的字元替換為OK,本次替換的單詞(\w)是3,d,4,7。把7算進來我認為是匹配到7的時候後面沒有字元了是空也不是數字所以被替換了,如果不對還請大神指正哈。

物件屬性

  • global是否全文搜尋,預設為false,修飾符中的g;
  • ignoreCase 是否大小寫敏感,預設為false,修飾符中的i;
  • multiline多行搜尋,預設為false,修飾符中的m;
  • lastIndex是當前表示式匹配內容的最後一個字元的下一個位置(有點繞哈,後面會解釋);
  • source 正規表示式的文字字串; 舉個栗子:
var reg = /\w/gim;
reg.global // true
reg.ignoreCase //true
reg.source // "\w"
複製程式碼

方法

方法一

  • RegExp.prototype.test(str) 用於測試字串引數中是否存在匹配正規表示式模式的字串,如果存在則返回true,否則返回false; 舉個栗子:
var reg1 = /\w/;
reg1.test('a'); // true
reg1.test('#'); // false
reg1.test('a'); // true
reg1.test('#'); // false
複製程式碼

再舉個栗子:

var reg2 = /\w/g;
reg2.test('a'); // true
reg2.test('#'); // false
reg2.test('a'); // false 
reg2.test('a'); // true
reg2.test('a'); // false 
複製程式碼

看到區別了麼?當全域性檢索時為什麼第二次執行reg2.test('a');時返回false呢?現在就要說說上文提到的物件屬性lastIndex啦,沒記住的回到上面看看定義,當第一次執行時我們獲取到的lastIndex是1,那下一次就會從2的位置開始執行,而我們可以知道2的位置是沒有字元的,所以返回false,第三次執行的時候有返回了true是因為查詢到沒有字元了lastIndex又重置了。同樣的你也可以測試reg2.test('aaa')第四次執行的時候就會是false了,需要知道的是,只有在全域性檢索時(g)lastIndex才會生效,否則的話只會返回 0 哦

方法二

  • RegExp.prototype.exec(str)使用正規表示式模式對字串執行搜尋,並將更新全域性RegExp物件的屬性以反映匹配結果。如果沒有匹配的文字則返回null,否則返回一個陣列:
    • index宣告匹配文字的第一個字元的位置;
    • input存放被檢索字串的string
非全域性呼叫

呼叫非全域性的RegExp物件的exec()方法時,返回陣列

  • 第一個元素是與正規表示式相匹配的文字
  • 第二個元素是與RegExp物件的第一個子表示式(上文中的分組)相匹配的文字(如果有的話)
  • 第二個元素是與RegExp物件的第二個子表示式(上文中的分組)相匹配的文字(如果有的話),以此類推 舉個栗子:
var reg = /\d(\w)(\w)\d/;
var text = '1az2bc3cf4df5gf';
var regexec =  reg.exec(text);
console.log(reg.lastIndex + '\t' + regexec.index + '\t' + regexec.toString()); //0	0	1az2,a,z
複製程式碼

因為是非全域性呼叫所以reg.lastIndex返回 0;regexec.index 返回了0,匹配到的文字的第一個字元是"1",index也就是0,regexec返回的陣列第一元素是與reg相匹配的文字,第二個元素是該文字中的符合正規表示式中第一個分組(\w)的文字是"a"後面的z同理。

全域性呼叫

再來看看全域性呼叫的例子

var reg = /\d(\w)(\w)\d/g;
var text = '1az2bc3cf4df5gf';
while(regexec = reg.exec(text)){
	console.log(reg.lastIndex + '\t' + regexec.index + '\t' + regexec.toString()); 
}
// 4	0	1az2,a,z
// 10	6	3cf4,c,f
複製程式碼

全域性呼叫 lastIndex 生效 分別讀取到1az23cf4的下一個字元的位置,後面與非全域性呼叫同理,不過全域性呼叫返回的是整段字串符合規則的文字。

嗯哼,這篇文章就到這裡了,如果對你有所幫助點個贊啦貓大在此謝過啦 本文會在個人部落格更新的哦,博主可好了,有空溜達溜達~~~

相關文章