正則表達式入門(上)---字符組和量詞

相信很多人都碰到過需要用正則匹配字符串的時候,遇到了又不會寫,上網一通亂搜,也看不明白那些鬼畫符是個什麼意思,就當黑箱調來改去的經歷。

但其實如果只是想看懂簡單正則表達式的話,並沒有那麼困難。符號雖多,但仍有線索可尋。它的內容可以大致劃分爲字符組量詞分組斷言四部分

這四個部分的表示方法都和這三個括號()[]{}息息相關,簡單的對應關係如下:

  • 字符組 []
  • 量詞 {}
  • 分組 & 斷言 ()

接下來就讓我們以括號爲線索瞭解正則表達式吧


(爲了方便, 文中示例使用JavaScript, 可以直接粘貼到瀏覽器控制檯查看效果)

/bc/.test('abcd') //輸出true 判斷字符串'abcd'是否匹配表達式 'abc' /字符串/是js表示正則的語法
'abcd'.search(/bc/) //輸出1  搜索首次匹配的位置
'abcd'.match(/bc/)[0] //輸出 獲取匹配到的字符串

在這裏插入圖片描述

一. 字符組 []

首先,在沒有特殊符號的情況下,正則只是簡單的匹配字符是否相等
比如 /b/.test('abc')匹配字符串中的b字符

但是往往我們會需要在一個位置上匹配一類字符,這在正則中被稱爲字符組,使用 中括號[] 表示

例如,需要查找字符串中是否存在數字的話,可以寫作'a1'.search(/[0123456789]/) //輸出1
意思是字符串’a1’中的下標爲1的字符可以由表達式/[0123456789]/匹配

但這樣也有個問題,表示英文字母得把26個字母挨個敲一遍,太長了; 不過放心,正則提供了一些簡寫的方式

1. 字符組的簡寫


1.1 範圍表示法

範圍表示法就是以[x-y]的形式表示x到y範圍的字符,按照ASCII的順序來
這樣,[0123456789]就可以寫作[0-9],小寫字母也就可以表示爲[a-z]

1.2 字符組簡記法

使用[0-9][a-z]已經可以很方便的表示數字和小寫字母了,但仍然有更簡單的表示,也就是簡記法

比如 表示數字的 [0-9] 可以寫成 \d,d表示數字(digit); 雖然\d這種寫法並沒有中括號,但它們是等價的;

下面是一些常用的簡記法和其等價的字符組的對應關係

簡記法 等價字符組 說明
\d [0-9] 數字 digit
\D [^0-9] 非數字
\s [ \t\r\n\v\f] 空白字符
\S [^ \t\r\n\v\f] 非空白字符
\w [0-9a-zA-Z_] 單詞字符(字母數字下劃線,包括中文)
\W [^0-9a-zA-Z_] 非單詞字符

2. 排除和轉義


2.1 排除型字符組

上面的表裏一二行出現了一個奇怪的現象,[0-9]只是加了個^,怎麼就從數字變成非數字了呢?不應該表示的是十個數字加上一個^這11個字符嗎?

這個^符號在字符組裏表示 取反 ,可以很方便的表示指定字符之外的字符集合這一概念,比如[^0-9]可以用來形容所有非數字字符

但是這樣的話 十個數字加上一個^這11個字符 又該怎麼表示呢?

其實,^只有緊跟在左中括號後面時,才表示取反的意思,如果改成[0-9^],那麼它的意思就只是簡單的匹配 十個數字或者^字符了

2.2 轉義字符

讓取反符號^變成普通字符並不只有更改位置這一種方式,還可以通過轉義字符來實現

說到轉義,首先不得不提到一個概念: 元字符 ; 這些字符不同於普通字符,它們在正則表達式中有折特殊的含義,例如 字符組[^0-9]裏面的^-,還有外層的中括號本身等;

如果就是想要匹配這些元字符本身,而不是它們所表達的特殊含義的話,可以在它們前面加上反斜槓\,來恢復它們的本來面目.

到這裏你也應該發現了,\也是元字符,需要用\\來表示它本身

下面是一些常見的元字符

元字符 作用 說明
- 範圍表示法
[0-9]表示[0123456789],按照ASCII編碼順序
只在字符組內有效
^ 排除型字符組
例:[^0-9]匹配除數字外的其他字符
只有緊跟在[後纔是元字符
[12^]匹配的是’1’ ,‘2’,’^'這三個普通字符
\ 轉義字符 匹配字符\本身需要\\
() 分組
[] 字符組
{} 量詞

二. 量詞 {}

上面所描述的都是匹配單個字符,如果需要匹配多個,比如YYYY-MM-DD這種格式的日期,只用\d的話是這樣的\d\d\d\d-\d\d-\d\d,很囉嗦;

正則中這種匹配多個字符的方式叫做量詞,寫作{n,m} ,比如4個數字是\d{4}
整個日期可以寫成\d{4}-\d{2}-\d{2}

量詞的一般形式爲{m,n},用於限定{}前面的元素出現的次數,n和m分別爲出現次數的上下限(閉區間)

量詞 說明
{n} 必須出現n次
{m,n} 出現m到n次
{m,} 至少出現m次,無上限
* 次數無上下限 , 等價於{0,}
+ 至少一次,等價於{1,}
? 0次或1次,等價於 {0,1}

貪婪和非貪婪模式

看到上面的表,你有沒有疑惑: 如果+意思是匹配 1到無窮次, 那麼如果有很多的字符都可以匹配的話,它是按多的來還是少的來呢?

具體來說, 用\d+匹配一段數字,是匹配全部還是隻選第一個?

這裏可以在控制檯裏嘗試一下 '1234'.match(/\d+/)[0] ,會發現它匹配上了全部的1234,所以說量詞默認是 貪婪 的,即儘量多的匹配能匹配上的字符

那麼相對應的就有非貪婪模式(匹配儘量少的字符), 它的寫法是在量詞後面加上?

'1234'.match(/\d+/)[0]  // 1234
'1234'.match(/\d+?/)[0]  // 1

在這裏插入圖片描述

  • 可以簡單的理解爲
    • 貪婪模式下這個量詞匹配儘量多的字符
    • 非貪婪模式匹配儘量少的字符

有意思的是?本身也是一種量詞,兩個?連起來表示: 以非貪婪模式匹配前面的元素0或1次,考慮到要匹配儘量少的字符,那就是壓根不匹配

'ab'.match(/ab?/)[0]  // ?等價於量詞 {0,1} , 字符b可以匹配也可以不匹配, 因爲是貪婪模式,那就匹配上了
'ab'.match(/ab??/)[0] // 第一個?是量詞 ,第二個? 表示非貪婪模式

在這裏插入圖片描述

參考

正則指引

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章