正則表達式基本語法

    這兩天一直在時不時的和neo4j圖數據庫打交道。它的查詢語句可使用正則表達式,有一段時間沒有本身寫過正則表達式了,如今處於能看懂別人寫的正則表達式,可是本身寫不出來,語法規則都忘了。爲了方便接下來的工做,因此特意複習複習正則表達式的語法。javascript

正則表達式簡介

    正則表達式是用來匹配字符串的一系列匹配符,具有簡介高效的特色,在不少語言中都有支持(java、python、javascript、php等等)。在windows的cmd命令中也一樣支持,例如使用命令dir j*,那麼只會羅列出全部以j開頭的文件和文件夾。php

正則表達式基本語法

    正則表達式在在不一樣語言的支持語法略有不一樣,本文采用js的進行說明。js中使用正則表達式的方法爲str.match(/表達式/),即須要加兩個斜槓。如下全部的代碼段第一行爲代碼,第二行爲返回結果,實驗是在chrome控制檯進行的。java

    一直認爲最好的學習方式就是實際操做,理論誰都能講一大堆,可是實際作沒作出來還真不知道。一個奇葩現象就是教軟件工程的老師可能並無在軟件行業待過。python

普通匹配符

    普通匹配符能匹配與之對應的字符,默認區分大小寫。正則表達式

"Hello Regx".match(/H/)
["H", index: 0, input: "Hello Regx", groups: undefined]
複製代碼
正則標記符
  • i :不區分大小寫
  • g :全局匹配
  • m :多行匹配(暫無論它,我用的少)

    參數直接加在最後一個斜槓的後面,好比"Hello Regx".match(/regx/==i==),能夠加多個參數。chrome

"Hello Regx".match(/regx/i)
["Regx", index: 6, input: "Hello Regx", groups: undefined]
複製代碼

    以前是表達式一旦匹配成功,就再也不向字符串後面查找了,加上g後,表示進行全局查找。最後返回的是一個數組。數據庫

"Hello Regx".match(/e/g)
(2) ["e", "e"]
複製代碼
多匹配符
  • \d :匹配數字,即0~9
  • \w :匹配數字、字母、下劃線
  • . :匹配除換行的全部字符

    須要注意的是,上面全部的匹配符都只能匹配一個字符。編程

"Hello 2018".match(/\d/g)
// 使用\d,匹配字符串中的全部數字
(4) ["2", "0", "1", "8"]


"Hello 2018".match(/\w/g)
// 使用\w,匹配全部的數字和字母,須要注意沒有匹配到空格
(9) ["H", "e", "l", "l", "o", "2", "0", "1", "8"]


"Hello 2018".match(/./g)
// 使用.,匹配全部字符,包括空格
(10) ["H", "e", "l", "l", "o", " ", "2", "0", "1", "8"]


"Hello 2018".match(/\d\w./g)
// 分析一下這個爲何匹配到的是201,
// 首先\d找到第一個數字2,匹配成功,緊接着\w匹配到0,而後.匹配到1
// 整個正則表達式匹配成功,返回201
["201"]


"Hello 20\n18".match(/\d\w./g)
// 這裏匹配不成功,由於.不能匹配換行符,因此返回null
null


"Hello 2018".match(/\w.\d/g)
// 首先看這個正則式,\w.\d,它要求最後一個字符是數字
// \w.能一直匹配到空格,可是由於得知足\d,因此第一個匹配成功的是0 2
// 由於是全局匹配,因此會接着匹配後面的018,也匹配成功
(2) ["o 2", "018"]
複製代碼
自定義匹配符

    好比中國的手機號都是以1開頭,第二位只能是三、四、五、七、8,第3位只要是數字就行。如何匹配這樣的字符串?windows

  • [] :匹配[]中的任意一個字符
"152".match(/1[34578]\d/)
// 第二個字符能夠選擇中括號中的任意一個
["152", index: 0, input: "152", groups: undefined]
複製代碼

    若是在[]添加了^,表明取反。即[^]表示除了中括號中的字符都知足。數組

"152".match(/1[^34578]\d/)

null


"1a2".match(/1[^34578]\d/)
// 只要不是[]中的字符,都知足,包括回車符
["1a2", index: 0, input: "1a2", groups: undefined]
複製代碼
修飾匹配次數

    咱們的手機號有11位,除了前2位有要求,其餘9位度沒有要求,那麼是否是正則表達式就應該這樣寫呢?

1[^34578]\d\d\d\d\d\d\d\d\d
複製代碼

    很明顯,這樣寫太麻煩,確定有更好的方式,這裏就能夠修飾一下匹配次數啦。

  • ? :最多出現1次
  • + :至少出現1次
  • * :出現任意次數
  • {} :分下面四種狀況
    • {n}表明前面的匹配符出現n次
    • {n, m}出現次數在n~m之間
    • {n, }至少出現n次
    • {, m}最多出現m次

    例子很簡單,一看就懂,不浪費時間。

"15284750845".match(/1[34578]\d{9}/)
["15284750845", index: 0, input: "15284750845", groups: undefined]


"15".match(/1[34578]\d?/)
["15", index: 0, input: "15", groups: undefined]


"152".match(/1[34578]\d?/)
["152", index: 0, input: "152", groups: undefined]


"152".match(/1[34578]\d+/)
["152", index: 0, input: "152", groups: undefined]


"15".match(/1[34578]\d+/)
null
複製代碼
完整匹配

    按照上面的寫法會出現下面的問題。

"ya15284750845".match(/1[34578]\d{9}/)
// 不是電話號碼,也能匹配成功,須要進一步改進
["15284750845", index: 2, input: "ya15284750845", groups: undefined]
複製代碼
  • ^ :在[]中表明取反,但在外面表明從開始匹配
"ya15284750845".match(/^1[34578]\d{9}/)
// 如今就能從一開始匹配並且還得符合正則式纔算匹配成功
null


// 可是依舊會出現下面的問題
"1528475084523255".match(/^1[34578]\d{9}/)
// 不是電話號碼也能匹配成功,還要改進
["15284750845", index: 0, input: "1528475084523255", groups: undefined]
複製代碼
  • $ :表明持續匹配到結束
"1528475084523255".match(/^1[34578]\d{9}$/)
// 如今就能保證正確了,有^表示從開始匹配;
// 有$表示持續匹配到結束,即徹底匹配
null

/* 須要注意的是,一個字符串從開始匹配和從結束匹配都沒問題, 不表明整個字符串就沒問題,好比15284750845-15284750845 這個字符串從開始和從結束匹配都能成功,但其實是錯的 */
複製代碼
特殊符號

    到這裏發現正則表達式確實很強大,僅僅幾個簡單的符號就能匹配字符串,可是若是咱們要匹配的字符自己就是前面用到的符號怎麼辦呢?

  • 匹配像$、^等特殊符號時,須要加轉義字符\
"1.".match(/./)
//由於.能匹配除換行的全部字符,因此匹配到1
//但實際上咱們想匹配.這個字符
["1", index: 0, input: "1.", groups: undefined]


"1.".match(/\./)
// 只須要加一個轉義字符就能夠了,其餘相似
[".", index: 1, input: "1.", groups: undefined]
複製代碼
條件分支

    好比如今想匹配圖片的文件名,包括jpg、png、jpeg、gif等等,這是多個選項,因此須要像編程語言同樣,應該具有條件分支結構。

  • | :條件分支
  • () :有兩層含義
    • 括號中的內容成爲一個獨立的總體
    • 括號的內容能夠進行分組,單獨匹配,若不須要此功能,則(?:)
"1.jpg".match(/.+\.jpe?g|gif|png/)
// 這樣就能夠知足條件分支了,不過下面又出問題了
["1.jpg", index: 0, input: "1.jpg", groups: undefined]


"1.png".match(/.+\.jpe?g|gif|png/)
// 這裏沒有匹配到.和前面的文件名
["png", index: 2, input: "1.png", groups: undefined]


/* 其實咱們想告訴它的是,.和後面的每個條件分支的值都是一個獨立的總體 可是它把.+\.jpe?g、gif、png當成了各自獨立的總體 咱們並不想讓它這樣切分,因此咱們來告訴它怎麼分纔是正確的 */


"1.png".match(/.+\.(jpe?g|gif|png)/)
// 如今能夠匹配成功了,可是它多匹配了一個
// 由於括號的內容能夠進行分組,單獨匹配
(2) ["1.png", "png", index: 0, input: "1.png", groups: undefined]


// 因此最終寫法以下
"1.png".match(/.+\.(?:jpe?g|gif|png)/)
["1.png", index: 0, input: "1.png", groups: undefined]
複製代碼
貪婪與懶惰
// 首先看一個例子
"aabab".match(/a.*b/)
["aabab", index: 0, input: "aabab", groups: undefined]


/* 上面的匹配沒有什麼問題,但實際上aab也是能夠的 也就是aab也是符合條件的,那又是爲何呢? */
複製代碼

    由於在正則表達式中,默認是貪婪模式,儘量多的匹配,能夠在修飾數量的匹配符後面添加?,則表明懶惰。

// like this (^__^)
"aabab".match(/a.*?b/)
["aab", index: 0, input: "aabab", groups: undefined]
複製代碼

    到這裏應該就差很少了,再深刻的,就自我查詢知識了。

相關文章
相關標籤/搜索