正則表達式簡介

正則表達式是一種描述模式的方法,用來描述“部分字符串的查找問題”。每個正則表達式表示的都是一個字符串的集合。

1.基本操作

它主要有三種模式:

1.1連接操作

多個字符組成字符串,比如AB

1.2或操作

用"|"表示,可以在模式中指定多種可能的匹配,比如A|B,代表查找A或B

1.3閉包操作

可以將模式中的部分重復任意次,用*標記在需要重復的模式之后,表示閉包。比如A*B,代表由0個或多個A和一個B組成的字符串

1.4三種模式的優(yōu)先級

閉包操作 > 連接操作 > 或操作,比如

  • AB|C 代表{AB,C}
  • AB* 代表{A,AB,ABB,ABBB...}

通過()可以修改優(yōu)先順序,比如:

  • C(A|B)D 代表 {CAD,CBD};
  • (A|C)((B|C)D) 代表 {ABD,ACD,CBD,CCD};
  • (AB)*代表{‘’,AB,ABAB,ABABAB...}
2.縮略寫法

有時有的描述使用基本操作可能顯得比較冗長,比如想要表示可能是26個字母中的一個,就要寫成A|B|C|D....|X|Y|Z,正則表達式提供很多縮略寫法,上面可以簡寫為[A-Z]。

2.1字符集描述
名稱 寫法 舉例
通配符 . A.B(代表{A,任意字符1,任意字符2,..., B})
指定集合 包含在[]中 [ABcd]
范圍集合 包含在[]中,由-間隔 [a-z][0-9]
補集 包含在[]中,首字母為^ [^ABCD] (代表除了A,B,C,D意外的其他字符)
2.2閉包的簡寫
含義 記法 舉例 原始寫法
至少重復1次 + (AB)+ (AB)(AB)*
重復0或1次 ? (AB)? ∈|AB
重復n次 由{}指定次數(shù) (AB){3} (AB)(AB)(AB)
重復指定范圍內(nèi)的次數(shù) 由{}指定次數(shù)范圍 (AB){1-2} (AB)|(AB)(AB)
2.3轉(zhuǎn)義字符

某些字符,比如"\","|","*",".","(",")"等都是正則標的是的元字符,如果想要表示需要在前面添加轉(zhuǎn)義字符"\",例如匹配</br>要寫成let re = /<\/br>/

2.4三種括號的區(qū)分
記法 作用
() 改變優(yōu)先級
[] 代表某個集合
{} 用來指定重復次數(shù)
3.其他常用字符
記法 作用
\s 空格
\S 非空格
\d 數(shù)字
\D 非數(shù)字
\w 字符 ( 字母 ,數(shù)字,下劃線_ )
\W 非字符
4.js中正則表達式的運用:
4.1在js中的定義:
//方式1,可以傳入多個參數(shù),,第一個參數(shù)是正則規(guī)則,第二個是其他字符,比如全局g,忽略大小寫i
let re1 = new RegExp('a');  
let re2 = new RegExp('a','g');  //全局匹配
let re2 = new RegExp('a','i');  //忽略大小寫匹配
let re3 = new RegExp('a','gi');  //全局忽略大小寫匹配
//方式2
let re4 = /a/;   // 簡寫方法
let re5 = /a/g;
let re6=/a/gi;
4.2 test()

作用:test方法用來在字符串中查找符合正則的內(nèi)容,若查找到返回true,反之返回false。

用法:正則.test(字符串)

function test(){
  let re =/rr.y/;
  let testStr1 = 'array';
  let testStr2 = 'b';
  let result1 = re.test(testStr1);//true
  let result2 = re.test(testStr2);//false
}
4.3 search()

作用:在字符串搜索符合正則的內(nèi)容,搜索到就返回出現(xiàn)的位置(從0開始,如果有多個,返回第一個的位置), 如果搜索失敗就返回 -1

用法:字符串.search(正則)

function search(){
  let re = /a/i;//忽略大小寫查找a
  let testStr = 'NBA';
  testStr.search(re); //返回2
}
4.4 match()

作用:在字符串中搜索復合規(guī)則的內(nèi)容,搜索成功就返回內(nèi)容,格式為數(shù)組,失敗就返回null。

用法: 字符串.match(正則)

4.4.1 非全局匹配
function match() {
    let testStr = 'aa1bb12cc3dd';
    let re = /\d+/;
    testStr.match(re)//[ '1', index: 2, input: 'aa1bb12cc3dd' ]
}

非全局匹配的時候,返回的數(shù)據(jù)中包含了此次匹配詳細的信息,數(shù)組的第一個元素是這次匹配到的字符串,數(shù)組的index屬性是該字符串的index,最后的input是此次的輸入。

4.4.2 全局匹配

在全局匹配的模式下只會輸出簡單的結(jié)果,如果想要詳細的結(jié)果請使用exec方法

function match(){
  let testStr = 'aa1bb12cc3dd';
  let re = /\d+/g;//全局匹配至少出現(xiàn)一個數(shù)字的字符串
  testStr.match(re)//輸出:[ '1', '12', '3' ]
}
4.5 replace()

作用:查找符合正則的字符串,就替換成對應(yīng)的字符串。返回替換后的內(nèi)容。

用法1: 字符串.replace(正則,替換字符串)

function replace(){
   /**注意這兩個的差別,會導致不同的結(jié)果,是從左向右匹配的,比如下面的re1的匹配過程:
   * 1.找到所有的"北京仁科互動"替換
   * 2.找到所有的"仁科互動"替換
   * 3.找到所有的"仁科"替換
   */
  let re1 = /北京仁科互動|仁科互動|仁科/g;//全局或匹配
  let re2 =  /北京仁科互動|仁科|仁科互動/g;

  let testStr = '北京仁科互動的簡稱不是仁科而是仁科互動';
  let result1 = testStr.replace(re1,'a');//a的簡稱不是a而是a
  let result2 = testStr.replace(re2,'a');//a的簡稱不是a而是a互動

上面的代碼只是簡單的將匹配字符串換成了單個a,如果想"北京仁科互動"對應(yīng)“aaaaaa”,"仁科"對應(yīng)“aa”,需要使用第二種寫法

用法2: 字符串.replace(正則,回調(diào)函數(shù))
回調(diào)函數(shù)的參數(shù)是被匹配的字符串,返回值是替換字符串

function replace2(){

  let re = /北京仁科互動|仁科互動|仁科/g;

  let testStr = '北京仁科互動的簡稱不是仁科而是仁科互動';
  let result = testStr.replace(re,(matchStr) => {

    //matchStr就是re中定義的所要匹配的字符串,比如這里一次是:"北京仁科互動","仁科互動","仁科"

    let result='';
    for(let i = 0, len = matchStr.length; i < len; i++){
      result+='a';
    }

    return result;
  });

  console.log(result);//打印結(jié)果:aaaaaa的簡稱不是aa而是aaaa
}

回調(diào)函數(shù)的第二個參數(shù)是matchStr在字符串中的角標,比如修改下上面的代碼:

let result = testStr.replace(re,(matchStr,index) => {
    console.log(index)//依次打印0,11,15
    return 'a';
  });
4.6 exec()

作用:用來檢索字符串中正則表達式的匹配,如果匹配到了那么就返回一個存放有結(jié)果的數(shù)組,如果沒有匹配到就返回一個null。

用法:正則.exec(字符串)

4.6.1 非全局匹配

function exec() {
    let re = /nba|好看/;

    let testStr = 'nba要比cba好看的多';
    let match1 = re.exec(testStr);
    console.log(match1);//[ 'nba', index: 0, input: 'nba要比cba好看的多' ]
    console.log(re.lastIndex);//lastIndex => 0

    let match2 = re.exec(testStr);
    console.log(match2);//[ 'nba', index: 0, input: 'nba要比cba好看的多' ]
    console.log(re.lastIndex);////lastIndex => 0
}

可以看到非全局匹配時,返回的數(shù)組與調(diào)用方法 String.match() 返回的數(shù)組是相同的:返回的結(jié)果依次是:匹配到的字符串,該字符串在輸入源中所在的index,輸入源;
此外match1和match2的結(jié)果是相同的,而寫兩個match是為了和下面的全局匹配做比較的。

4.6.2 全局匹配

在全局匹配下,exec() 的行為就稍微復雜一些。每次執(zhí)行exec()以后,RegExpObject的lastIndex屬性會指向此次匹配的字符串的最后一個字符所在的角標,在下次匹配時會在 RegExpObject 的 lastIndex 屬性指定的字符處開始檢索字符串 string。當 exec() 找到了與表達式相匹配的文本時,在匹配后,它將把 RegExpObject 的 lastIndex 屬性設(shè)置為匹配文本的最后一個字符的下一個位置。這就是說,
可以通過反復調(diào)用 exec() 方法來遍歷字符串中的所有匹配文本。當 exec() 再也找不到匹配的文本時,它將返回 null,并把 lastIndex 屬性重置為 0。

function execGlobal() {
    let re = /nba|好看/g;

    let testStr = 'nba要比cba好看的多';
    let match1 = re.exec(testStr);
    console.log(match1);//[ 'nba', index: 0, input: 'nba要比cba好看的多' ]
    console.log(re.lastIndex);//lastIndex => 3


    let match2 = re.exec(testStr);
    console.log(match2);//[ '好看', index: 8, input: 'nba要比cba好看的多' ]
    console.log(re.lastIndex);////lastIndex => 10

}

在一般情況下我們會寫一個循環(huán)來進行全局匹配:

function execGlobalWhile() {
    let re = new RegExp('好看|nba','gi');

    let testStr = 'nba要比cba好看的多';
    let match;

    while (match = re.exec(testStr)){
        console.log(match);
    }
    //打印結(jié)果如下:
    //[ 'nba', index: 0, input: 'nba要比cba好看的多' ]
    //[ '好看', index: 8, input: 'nba要比cba好看的多' ]

}
4.7 例子
4.7.1 查找出現(xiàn)次數(shù)最多的字符
function findMore(){
  let str = 'assssjdssskssalsssdkjsssdss';
  let arr = str.split(''); //把字符串轉(zhuǎn)換為數(shù)組
  str = arr.sort().join(''); //首先進行排序,這樣結(jié)果會把相同的字符放在一起,然后再轉(zhuǎn)換為字符串
  //alert(str);  // aaddjjkklsssssssssssssssss

  let value = '';
  let index = 0;
  let re = /(\w)\1+/g;  //匹配字符,且重復這個字符,重復次數(shù)至少一次。
  str.replace(re,function($0,$1){
    //alert($0);   代表每次匹配成功的結(jié)果 : aa dd jj kk l sssssssssssssssss
    //alert($1);  代表每次匹配成功的第一個子項,也就是\w:  a d j k l S

    if(index<$0.length){  //如果index保存的值小于$0的長度就進行下面的操作
      index = $0.length;  // 這樣index一直保存的就在最大的長度
      value = $1;  //value保存的是出現(xiàn)最多的這個字符
    }

  });

  console.log('最多的字符:'+value+',重復的次數(shù):'+index);  // 最多的字符:s,重復的次數(shù):17
}
4.7.2在react native中實現(xiàn)hightlightText

就是類似于百度搜索的關(guān)鍵字高亮顯示:
1.在render方法中返回如下:

render(){
  let searchKeys = this.props.searchKeys;
  //排序是為了讓長度比較長的key在前面
  searchKeys.sort((k1,k2) => k2.length - k1.length);
  return <Text style={this.props.contentStyle}
                             numberOfLines={1}>
                    {this._getPieceTexts(this.props.textToHighlight, searchKeys)}
                </Text>
}

2._getPieceTexts:

    _getPieceTexts(textToHighlight, keys) {
        let pieces = this._getPieces(textToHighlight, keys);

        return pieces.map(piece => {
            let text = textToHighlight.substring(piece.start, piece.end);
            return piece.highlight ?  this._getText(text) : text;

        });

    }

上面的_getPieces方法就是利用正則的exec方法,將原字符串中每一個片段都保存為一個對象,該對象格式如下:

{
    start,//片段開始位置
    end,//片段結(jié)束位置
    highlight//該片段是否要高亮顯示
}

3._getPieces方法如下

_getPieces(textToHighlight, keys = []) {

        let re = new RegExp(keys.join('|'), this.props.caseSensitive ? 'g' : 'gi');
        let match;
        let pieces = [];
        let result =[];
        while ((match = re.exec(textToHighlight))) {
            let start = match.index;
            let end = re.lastIndex;
            pieces.push({
                start: start,
                end: end,
            });
        }

        let totalLength = textToHighlight.length;

        if (pieces.length === 0) {
            this._append(0, totalLength, false, result);
        } else {
            let lastIndex = 0;
            pieces.forEach((piece) => {
                this._append(lastIndex, piece.start, false, result);
                this._append(piece.start, piece.end, true, result);
                lastIndex = piece.end;
            } );
            this._append(lastIndex, totalLength, false, result);
        }

        // console.log('result:' + JSON.stringify(result));
        return result;
    }

    _append(start, end, highlight, result) {
        if (end - start > 0) {
            result.push({
                start: start,
                end: end,
                highlight: highlight
            });
        }
    }

展示效果如下:

image.png

完整代碼請看github:https://github.com/wangzhen90/react-native-highlight-text

參考:https://www.cnblogs.com/moqing/archive/2016/07/13/5665126.html

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容