正則表達式

  數據/字符串處理是工做中常常能用到的,之前的作法大都是經過百度而後修改別人的代碼完成字符串處理,一直想系統的跟正則認識一番,因而有了這篇。java

點擊《正則表達式》可查看原文哦!
同時很是感謝雪峯大大和鑫大大的文章支持,點擊如下連接可查看參考原文。
雪峯大大的 標準對象/RegExp.
鑫大大的 粉絲羣第27期JS基礎小測答疑文字版python

  好的,接下來進入正題啦。正則表達式

正則表達式定義

  正則表達式是對字符串操做的一種邏輯公式,用事先定義好的一些特定字符、及這些特定字符的組合,組成一個「規則字符串」,這個「規則字符串」用來表達對字符串的一種過濾邏輯。
舉個例子:
  '00\d'能夠匹配'007',‘008’,其中‘\d’即匹配數字。數組

語法

元字符

 字 符   描 述  反義字符   描 述
$ 匹配輸入字符串的結尾位置
^ 匹配輸入字符串的開始位置
. 匹配除換行符 \n 以外的任何單字符
\b 匹配單詞邊界 \B 匹配不是單詞開頭或結束的位置
\d 匹配數字 \D 匹配任意非數字的字符
\w 匹配字母,數字,下劃線 \W 匹配任意不是字母,數字,下劃線 的字符
\s 匹配空格 \S 匹配任意不是空白符的字符
[abc] 匹配包含括號內元素的字符 [^abc] 匹配除了abc之外的任意字符

量詞

 字 符   描 述  帶?字符   描 述
* 重複至少0次 *? 重複任意次,但儘量少重複
+ 重複至少1次 +? 重複至少1次,但儘量少重複
? 重複0次或1次 ?? 重複0次或1次,但儘量少重複
{n} 重複n次
{n,} 重複至少n次 {n,}? 重複至少n次,但儘量少重複
{n,m} 重複n-m次 {n,m}? 重複n-m次,但儘量少重複

特殊字符

 字 符   描 述  字 符   描 述
\cx 匹配由x指明的控制字符。
\f 匹配一個換頁符。等價於 \x0c 和 \cL。 ( ) 標記一個子表達式的開始和結束位置。
\n 匹配一個換行符。等價於 \x0a 和 \cJ。 | 指明兩項之間的一個選擇,或
\r 匹配一個回車符。等價於 \x0d 和 \cM。 [ 標記一箇中括號表達式的開始
\s 匹配任何空白字符,包括空格、製表符、換頁符等等。 \ 將下一個字符標記爲或特殊字符、或原義字符、或向後引用、或八進制轉義符
\S 匹配任何非空白字符。等價於 [^ \f\n\r\t\v]。 { 標記限定符表達式的開始。
\t 匹配一個製表符。等價於 \x09 和 \cI。 \v 匹配一個垂直製表符。等價於 \x0b 和 \cK。

舉例說明

  • 數字、字母匹配(\d匹配數字,\w匹配任意字母,數字,下劃線)
    可用00\d能夠匹配007
    \d\d\d能夠匹配任意三位數字,如:123
    \w\d\w能夠匹配l0lwordpress

  • .匹配任意字符,則
    any.可匹配anyaanybanycanyd ......ui

  • 配合上量詞再看看
    \d{3}表示匹配3個數字,例如010 \d{3,8}表示3-8個數字,例如1234567this

  • 再加上咱們的範圍
    [0-9a-zA-Z\_]能夠匹配一個數字、字母或者下劃線
    [0-9a-zA-Z\_]+能夠匹配至少由一個數字、字母或者下劃線組成的字符串,好比a1000_ZPy3000等等
    [a-zA-Z\_][0-9a-zA-Z\_]*能夠匹配由字母或下劃線開頭,後接任意個由一個數字、字母或者下劃線組成的字符串,也就是Python合法的變量
    [a-zA-Z\_][0-9a-zA-Z\_]{0, 19}更精確地限制了變量的長度是1-20個字符(前面1個字符+後面最多19個字符)spa

  • 啊,還有咱們的選擇字符和定位
    A|B能夠匹配A或B,因此(P|p)ython能夠匹配Python或者python
    ^表示行的開頭,^\d表示必須以數字開頭 $表示行的結束,\d$表示必須以數字結束
    你可能注意到了,py也能夠匹配python,可是加上^py$就變成了整行匹配,就只能匹配pyprototype

  • 字符串的切割
    最經常使用的應該就是split切割了,可是當字符串之間不只僅是單一字符鏈接,切割就會出現問題,好比下面的例子code

    //出現多餘空格狀況:
        'a b c'.split(' '); // ['a', 'b', '', '', 'c']
    
    //嗯,沒法識別連續的空格,用正則表達式試試:
    'a b c'.split(/\s+/); // ['a', 'b', 'c']
    //不管多少個空格均可以正常分割。加入,試試:
    
    'a,b, c d'.split(/[\s\,]+/); // ['a', 'b', 'c', 'd']
    //再加入;試試:
    
    'a,b;; c d'.split(/[\s\,\;]+/); // ['a', 'b', 'c', 'd']
    //若是用戶輸入了一組標籤,下次記得用正則表達式來把不規範的輸入轉化成正確的數組。
    複製代碼
  • 字符串的分組應用
    除了簡單地判斷是否匹配以外,正則表達式還有提取子串的強大功能。用()表示的就是要提取的分組(Group)。好比:^(\d{3})-(\d{3,8})$分別定義了兩個組,能夠直接從匹配的字符串中提取出區號和本地號碼:

    var re = /^(\d{3})-(\d{3,8})$/;
    re.exec('010-12345'); // ['010-12345', '010', '12345']
    re.exec('010 12345'); // null
    複製代碼

    若是正則表達式中定義了組,就能夠在RegExp對象上用exec()方法提取出子串來。
    exec()方法在匹配成功後,會返回一個Array,第一個元素是正則表達式匹配到的整個字符串,後面的字符串表示匹配成功的子串。
    exec()方法在匹配失敗時返回null。

    提取子串很是有用。來看一個更兇殘的例子:

    var re = /^(0[0-9]|1[0-9]|2[0-3]|[0-9])\:(0[0-9]|1[0-9]|2[0-9]|3[0-9]|4[0-9]|5[0-9]|[0-9])\:(0[0-9]|1[0-9]|2[0-9]|3[0-9]|4[0-9]|5[0-9]|[0-9])$/;
    re.exec('19:05:30'); // ['19:05:30', '19', '05', '30']
    複製代碼

    這個正則表達式能夠直接識別合法的時間。可是有些時候,用正則表達式也沒法作到徹底驗證,好比識別日期:

    var re = /^(0[1-9]|1[0-2]|[0-9])-(0[1-9]|1[0-9]|2[0-9]|3[0-1]|[0-9])$/;   
    複製代碼

    對於'2-30','4-31'這樣的非法日期,用正則仍是識別不了,或者說寫出來很是困難,這時就須要程序配合識別了。


如下內容參見鑫大大博客內容:

  • 中英文之間須要增長空格
    首先,咱們的思路應該是「中文」、「英文」、「空格」,因而咱們可獲得 /(中文+英文+|英文+中文+)/g 這樣的符號表達
    轉換成正則符號即: /([\u4e00-\u9fa5]+[A-Za-z]+|[A-Za-z]+[\u4e00-\u9fa5]+)/g 其中[\u4e00-\u9fa5]表示中文字符匹配;[A-Za-z]表示所有的英文字母。斜槓後面的g表示全局匹配,除了g,還有i和m。其中i表示不區分大小寫,m表示支持多行匹配。 這裏的括號和加號可化簡,則最終可表達爲: 
    /[\u4e00-\u9fa5][a-z]|[a-z][\u4e00-\u9fa5]/gi

  • 全角標點與其餘字符之間不加空格
    這裏若是直接用正則表達式,會顯得冗餘且不易懂,故使用RegExp對象簡化

    // 全角標點字符們 
    var strPunct = '!()【】『』「」《》「」‘’;:,。?、';  
    // 使用管道符鏈接 
    var regPunct = strPunct.split('').join('|');  
    // 此時的正則表達式 
    new RegExp('['+ regPunct +'] +| +['+ regPunct +']', 'g');  
    複製代碼

    這樣就顯得簡潔多了
    其中,空格使用普通空格字符進行匹配的,而不是\s,這樣能夠避免把換行符也過濾掉了

  • 不重複使用標點符號
    這裏的標點指中文標點,由於英文標點不重複,有些不切實際,例如空字符串'',就是合法的重複標點。
    使用正則表達式:

    /(\~|\`|\!|\[|\]|\{|\}|\;|\:|\"|\'|\,|\<|\.|\>|\/|\?|\!|\·|\【|\】\「\」|\;|\:|\「|\」|\,|\《|\。|\》|\、|\?)\1+/g 複製代碼

    使用RegExp對象簡化:

    new RegExp(`(${regPunct})\\1+`, 'g')
    複製代碼

    這樣就是不使用重複中文標點了。
    其中,這裏的\1有必要好好說下。\1表示捕獲匹配,表示捕獲第一個分組括號中匹配的值,你能夠理解爲代稱。在正則表達式中,每個分組括號()都自帶一個看不見的序號,從前日後依次是分組一,分組二,分組三……
    這裏的\1就表示匹配的第一個標點,後面跟了個+則表示,這裏重複標點2個或多個都匹配。
    捕獲分組不只存在於正則表達式中,當咱們使用replace方法進行正則替換的時候,也存在與替換方法中,使用美圓符號$外加數字表示,例如先後空格過濾trim()方法的簡易polyfill:

    if (!''.trim) {
        String.prototype.trim = function () {
      	// $1表示第一個()中匹配的值
      	return this.replace(/^\s*(.*?)\s*$/, '$1');
        };
    }
    複製代碼

    其中'$1'並非替換成字符串$1意思,而是替換成第一個()中匹配的值,在這裏表示首尾空格之外的值。 若是咱們須要對捕獲分組內容進行額外處理,能夠把第二個參數做爲function處理,例如:

    this.replace(/^\s*(.*?)\s*$/, function (matches, $1) {
        // matches表示完整匹配內容(包括先後空格)
        // $1則表示第一個()中匹配的值 
        // 此時就能夠對$1進行處理,返回咱們須要的值
    })
    複製代碼
  • 破折號先後須要增長一個空格
    這個比較簡單,可直接得到:

    /\S——|——\S/g
    複製代碼
  • 使用全角中文標點
    正則表達式

    /([^A-Za-z][\~|\`|\!|\[|\]|\{|\}|\;|\:|\"|\'|\,|\<|\.|\>|\/|\?][^A-Za-z])/g 複製代碼

    使用RegExp對象處理:

    var strPunctHalf = '!()[]"\';:,.?';
    // 不一樣於全角字符,半角字符須要加轉義
    var regPunctHalf = strPunctHalf.split('').join('|\\');
    // 此時的正則表達式
    new RegExp(`[\u4e00-\u9fa5][a-z]*( *[${regPunctHalf}] *)|( *[${regPunctHalf}] *)[a-z]*[\u4e00-\u9fa5]`, 'gi');
    複製代碼
  • 數字使用半角
    /[\uFF10-\uFF19]+/g

  • 遇到完整的英文整句,其內容使用半角標點
    正則表達式

    /(\「[A-Za-z\s\~|\`|\!|\;|\:|\"|\'|\,|\<|\.|\>|\/|\?]*[\!|\·|\;|\:|\「|\」|\,\。|\、|\?][^\」]*\」)|(\《[A-Za-z\s\~|\`|\!|\;|\:|\"|\'|\,|\<|\.|\>|\/|\?]*[\!|\·|\;|\:|\「|\」|\,\。|\、|\?][^\》]*\》)/g 複製代碼

    RegExp對象處理:

    new RegExp(`([a-z]+[${regPunct}|\\s])+[a-z]*([${regPunct}|\\s][a-z]+)+`, 'gi')
    複製代碼

  正則表達式的介紹就先到這裏啦,怎麼樣,動手使用吧~~~

相關文章
相關標籤/搜索
本站公眾號
   歡迎關注本站公眾號,獲取更多信息