正規表示式學習筆記(1)-認識正則

johnchou發表於2021-09-09

寫在前面:
由於慕課網不能寫超過20000字的手記,因此此篇文章做了拆分。另外本篇手記為個人學習所寫,相關摘錄以及引用在本系列最後一篇文章中已經貼出。

手記相關程式碼,請參考本人github地址:

1. 使用正則

建立正規表示式有兩種方式,一種是以字面量方式建立,另一種是使用RegExp建構函式來建立。

var expression = / pattern / flags;
var expression = new RegExp( pattern / flags );
var expression = new RegExp( patternStr, flags );

// example
var regexp = /regexp/g;
var regexp = new RegExp('regexp', 'g');
var regexp = new RegExp(/regexp/g);

其中模式(pattern)部分可以是任何簡單或複雜的正規表示式,可以包含字元類、限定符、分組、向前查詢以及反向引用。
每個正規表示式都可帶有以或多個標誌(flags),用以表明正規表示式的行為。

注:flag為可選項,表示匹配模式,主要有一下3種標誌。

  • g : 表示全域性(global)模式,即模式將被應用於所有字串,而非在發現第一個匹配項時立即停止;
  • i : 表示不區分大小寫(case-insensitive)模式,即在確定匹配項時忽略模式與字串的大小寫;
  • m : 表示多行(multiline)模式,即在到達一行文字末尾時還會繼續查詢下一行中是否存在與模式匹配的項。
// global
var str = 'hello world, hello life',
    reg1 = /hello/,
    reg2 = /hello/g;

// 非全域性模式下,返回一個陣列
// 第一個參數列示匹配的字串
// index表示的是匹配字串在文字中的起始位置
// input表示引用的文字
str.match(reg1); // [ 'hello', index: 0, input: 'hello world, hello life' ]

// 全域性模式下的匹配返回所有匹配的值
str.match(reg2); // [ 'hello', 'hello' ]

// case-insensitive
var cStr = 'Hello world',
    cReg1 = /hello/,
    cReg2 = /hello/i;

cReg1.exec(cStr);   // null
cReg2.exec(cStr);   // [ 'Hello', index: 0, input: 'Hello world' ]

// multiline
var mStr = 'hello worldn hello life',
    mReg1 = /world$/,
    mReg2 = /world$/m;

// 結果為null,因為沒有啟用多行,world並不算mStr的結尾
mStr.match(mReg1);  // null
// 匹配成功,啟用多行之後,world變成第一行的結尾
mStr.match(mReg2);  // [ 'world', index: 6, input: 'hello worldn hello life' ]

1.1 RegExp 例項屬性

每個RegExp例項物件都會存在下列屬性:

  • global : 布林值,表示是否設定了g標誌
  • ignoreCase : 布林值,表示是否設定了i標誌
  • multiline : 布林值,表示是否設定了m標誌
  • lastIndex : 整數,表示開始搜尋下一個匹配項的字元位置,從0算起
  • source : 正規表示式字串表示,按照字面量形式而非傳入建構函式中的字串模式返回
var reg = /[hello] regexp/i;

reg.global;         // false
reg.ignoreCase;     // true
reg.multiline;      // false
reg.lastIndex;      // 0
reg.source;         // [hello] regexp

var reg2 = new RegExp('\[hello\] regexp', 'ig');

reg2.global;        // true
reg2.ignoreCase;    // true
reg2.multiline;     // false
reg2.lastIndex;     // 0
reg2.source;        // [hello] regexp 字面量形式返回

1.2 RegExp 例項方法

  • pattern.exec(str)

exec方法是RegExp的主要方法,主要用於提取捕獲組(這個後面後講到),它接收一個匹配字串作為引數,如果匹配成功,返回一個包含匹配項資訊的陣列;在沒有匹配到的時候返回null。

返回的陣列包含匹配的字串,同時另外包含兩個屬性:index 和 input。index表示的是匹配字串在文字中的起始位置,input表示匹配的字串。

非全域性模式匹配下,如果字串中含有與模式匹配的多個子字串,那麼只會返回第一個匹配項的結果。返回的陣列中下標為0的位置表示匹配到的字串,其餘位置表示匹配到的捕獲組資訊;而在全域性模式下(g),如果依次執行exec方法,依次返回的是每一個匹配項資訊的陣列。例如:

// 在非全域性模式下,始終返回第一個匹配項的資訊
var reg = /]*?)>/,
    str = "
helloregexp
"; var matches = reg.exec(str); matches[0]; //
matches[1]; // "" matches[2]; // div matches[3]; // class='hello' matches.index; // 0 reg.lastIndex; // 0 var matches = reg.exec(str); matches[0]; //
matches[1]; // "" matches[2]; // div matches[3]; // class='hello' matches.index; // 0 reg.lastIndex; // 0 // 在全域性模式匹配下,找到第一個匹配項資訊之後,如果繼續執行,會在字串中繼續查詢下一個匹配項 var reg1 = /]*?)>/g, str1 = "
helloregexp
"; var matches = reg1.exec(str1); matches[0]; //
matches[1]; // "" matches[2]; // div matches[3]; // class='hello' matches.index; // 0 reg1.lastIndex; // 19 var matches = reg1.exec(str1); matches[0]; // matches[1]; // "" matches[2]; // b matches[3]; // "" matches.index; // 19 reg1.lastIndex; // 22
  • pattern.test(str)

test方法主要用於檢測字串中是否存在與模式匹配的字串,常用語條件判斷。匹配成功返回true,否則返回false。例如:

var pattern = /d{2}-d{3}/,
    str = '29-234',
    str1 = '290-3345',
    str2 = '1-33245';
pattern.test(str);  // true
pattern.test(str1); // true
pattern.test(str2); // false

1.3 RegExp 建構函式屬性

建構函式靜態屬性,分別有一個長屬性名和一個短屬性名(Opera是例外,不支援短屬性名)。

長屬性名 短屬性名 說明
input $_ 最近一次要匹配的字串
lastMatch $& 最近一次的匹配項
lastParen $+ 最近一次匹配的捕獲組
leftContext $` input字串中lastMatch之前的文字
multiline $* 布林值,表示是否所有表示式都使用多行模式
rightContext $' input字串中lastMatch之後的文字
var pattern = /(.)or/,
    str = 'this is a normal string or meaningful';

if (pattern.test(str)) {
    console.log(RegExp.input);          // this is a normal string or meaningful
    console.log(RegExp.lastMatch);      // nor
    console.log(RegExp.lastParen);      // n
    console.log(RegExp.leftContext);    // this is a
    console.log(RegExp.multiline);      // false
    console.log(RegExp.rightContext);   // mal string or meaningful

    console.log(RegExp['$_']);          // this is a normal string or meaningful
    console.log(RegExp['$&']);          // nor
    console.log(RegExp['$+']);          // n
    console.log(RegExp['$`']);          // this is a
    console.log(RegExp['$*']);          // false
    console.log(RegExp['$'']);         // mal string or meaningful
}

1.4 用於模式匹配的String方法

  • str.search(pattern)

它的引數是一個正規表示式,返回第一個與之匹配的子串的起始位置,如果找不到匹配的子串,它將返回-1。例如:

var str = 'JavaScript is not java',
    pattern = /Java/i,
    pattern2 = /Java/ig;
console.log(str.search(pattern));   // 0
console.log(str.search(pattern2));  // 0

注:如果search()的引數不是正規表示式,則首先會透過RegExp構造方法將它轉換成正規表示式,search()方法不支援全域性檢索,因為它忽略正規表示式引數中的修飾符g

  • str.replace(subStr | pattern, replaceStr | function)

第一個引數是正規表示式或者是字串,第二個引數是要替換的字串。如果第一個引數是正規表示式,直接進行模式匹配,若為字串,則會檢索整個字串進行替換,而不會轉化為正規表示式。例如:

var str = 'JavaScript is not java',
    pattern = /Java/i;

console.log(str.replace(pattern, 'live'));     // liveScript is not java
console.log(str.replace('Java', 'live'));      // liveScript is not java

// function
var str2 = '123-456-789',
    pattern2 = /(d+)/g;

str2.replace(pattern2, function(v) {
    // 會執行三次
    // 第一次列印123
    // 第二次列印456
    // 第三次列印789
    console.log(v);
});

/**
 * 第一個參數列示匹配的字串
 * 第二個參數列示匹配的元組(如果沒有元組,則實際上回撥函式只有三個值,即此時的d值會為undefined)
 * 第三個參數列示字串匹配的開始索引
 * 第四個參數列示匹配的字串
 */
str2.replace(pattern2, function(a, b, c, d) {
    // 會執行三次
    // 第一次列印123, 123, 0, 123-456-789
    // 第二次列印456, 456, 4, 123-456-789
    // 第三次列印789, 789, 8, 123-456-789
    console.log(a, b, c, d);
});

// 此時沒有進行元組匹配
str2.replace(/d+/g, function(a, b, c, d) {
    // 會執行三次
    // 第一次列印123, 0, 123-456-789, undefined
    // 第二次列印456, 4, 123-456-789, undefined
    // 第三次列印789, 8, 123-456-789, undefined
    console.log(a, b, c, d);
});
  • str.match(pattern)

match方法接收一個正規表示式,如果是在全域性模式匹配下,匹配失敗返回null,匹配成功會返回一個陣列,包含所有匹配的值;如果是非全域性模式,則返回第一個匹配項陣列資訊,陣列中第一個元素為匹配字串,餘下為匹配的捕獲組,另外這個陣列還有兩個屬性,index和input,index表示匹配字串的開始索引,input表示匹配的字串。例如:

var str3 = 'yuzhongzi_91@sina.com',
    pattern3 = /^([a-zA-Z][wd]+)@([a-zA-Z0-9]+)(.([a-zA-Z]+))+$/,
    matches;

matches = str3.match(pattern3);
console.log(matches[0]);        // yuzhongzi_91@sina.com
console.log(matches[1]);        // yuzhongzi_91
console.log(matches[2]);        // sina
console.log(matches[3]);        // .com
console.log(matches[4]);        // com
console.log(matches.index);     // 0
console.log(matches.input);     // yuzhongzi_91@sina.com
  • str.split(pattern | subStr, [ howmany ])

split可以接收兩個引數,第二個引數可選,表示返回陣列的最大長度。其中第一個引數是指定的分隔符,可以使正規表示式或者是字串。例如:

var str4 = 'Hope left life become a cat.',
    pat1 = /s/,
    pat2 = ' ';

console.log(str4.split(pat1));      // [ 'Hope', 'left', 'life', 'become', 'a', 'cat.' ]
console.log(str4.split(pat2, 2));   // [ 'Hope', 'left' ]

來自 “ ITPUB部落格 ” ,連結:http://blog.itpub.net/4422/viewspace-2798674/,如需轉載,請註明出處,否則將追究法律責任。

相關文章