iT邦幫忙

2019 iT 邦幫忙鐵人賽

DAY 12
0
自我挑戰組

學JS的心路歷程系列 第 12

學JS的心路歷程 Day12-正規表達式 Regular Expression

今天我們來看正規表達式,在談到為什麼需要多學這個之前,先來看個範例。

假設需要判斷輸入字串是否含有"apple"

var text="A apple a day keeps the doctor away";
function hasApple(val){
    hasStr = val.indexOf("apple");
    if(hasStr === -1) return false;
    
    return true;
}
hasApple(text);//true

看起來很簡單,對吧!但如果今天要判斷的不只一個的話呢?
只能不段增加變數和判斷式長度嗎?這聽起來就是個寫"糙 code "的開始。
(想知道什麼是 "糙 code " 可以參考這個系列喔 可不可以不要寫糙 code

那麼該怎麼作呢?很簡單, JS 有提供給我們正規表達式,可以這樣寫:

var text="A apple a day keeps the doctor away";
function hasApple(val){
    return /apple/.test(text)
}
hasApple(text);//true

是不是比上面的例子乾淨許多了呢!

既然這樣,話不多說我們趕緊來看到底怎麼用吧。

在 JS 中我們有兩種方式可以建立正規表達式:

  • 透過正規表達式實值
  • 建立一個 RegExp 實例
const pattern = /apple/;
const otherPattern = new RegExp("test");

兩種方式都能建立出相同的正規表達式,但如果在一開始就知道了正規表達式的內容,會一般會比較推薦用實值的方式建立,建構式方式比較用於程式執行階段時,動態透過字串建立。
--《忍者 JavaScript 開發技巧探祕》,第十章

接下來會列出常見的語法以及與之相關的方法,可能會讓你認為難以理解,但我會盡我所能的用範例講解。

首先我們要知道正規表達式都會包含兩個 / ,千萬不要跟 \ 搞混,他是有特殊用法的!

一般字元:

語法 說明
/apple/ 含有 apple 的字串
/./ 含有任意字元的字串
/apple./ 含有apple 後面接任意字元的字串

範例:

var text = "A apple a day keeps the doctor away.I have pen , I have apple.Uh ! ApplePen!!";

/apple/.test(text);//true
text.match(/./);//["A", index: 0, input: "A apple a day keeps the doctor away.I have pen , I have apple.Uh ! ApplePen!!", groups: undefined]
text.replace(/./,"hi")
//"hi apple a day keeps the doctor away.I have pen , I have apple.Uh ! ApplePen!!"

這邊我們可以看到

  • test 是回傳字串內"是否"含有正規表達式指定的字元。
  • match 會根據 正規表達式回傳符合字串的陣列。
  • replace 會根據 正規表達式取代符合字串。

旗標值

語法 說明
/apple/i 不區分英文大小寫
/apple/g 全域匹配,只要符合就會回傳
m 多行匹配
y 進行黏性匹配(sticky matching),只會對最後一次符合處之後進行匹配 ,需要配合設定 lastIndex
u 對 unicode 數值作跳脫

範例:

var text = "A apple a day keeps the doctor away.I have pen , I have apple.Uh ! ApplePen!!";
/apple/.test(text);//true
text.match(/apple/g);//["apple", "apple"]
text.match(/apple/ig);//["apple", "apple", "Apple"]
text.replace(/apple/ig,"hi");//"A hi a day keeps the doctor away.I have pen , I have hi.Uh ! hiPen!!"

y這邊我特別拉出來說明,因為看了官網文件還是不太懂,搜尋很久才得到解答:

var str = "I have apple";
          //0123456789
var regx = /apple/y;
regx.lastIndex = 7;
regx.test(str);//true
regx.test(str);//false

y 會根據你設置的 lastIndex 位置開始匹配,不匹配則回傳否,不會在往下尋找,
lastIndex 重製為 0 。

通常使用於避免前綴字串影響正規表達式時。

符號

語法 說明
^ 字串開頭必須符合條件字元
$ 字串結尾必須符合條件字元
* 字元可以出現0次以上
? 字元可以出現1次或0次
+ 字元至少出現1次
{} 指定字元重複出現次數
{1,} 指定字元重複出現1次以上
{,3} 指定字元重複出現3次以下
/^test/.test("est test");//false
/test$/.test("est test");//true
/t+est/.test("est");//false
/t?est/.test("est");//true
/t*est/.test("ttttest");//true
/t{,3}est/.test("ttttest");//false

比對多個字元

語法 說明
[] 字串若含有 [xxx] 裡面字元則匹配
[^] 字串若不含有 [^xxx] 裡面字元則匹配
[0-9] 字串若含有 數字0到9 字元則匹配
[a-z] 字串若含有 a到z 字元則匹配
/^[a-z]/.test("est test");//true
/[0-9]$/.test("est test");//false
/^[^a-z]/.test("est test");//false
/[0-9]/.test("1est test");//true

特殊字元

我們前面有提到過 \ 會有特殊用途,這邊就是囉!

語法 說明
d 任何數字字元,等於[0-9]
D 任何非數字字元,等於[^0-9]
w 任何數字字元字母底線,等於 [A-Za-z0-9_]
W 任何非數字字元字母底線,等於 [^A-Za-z0-9_]
s
S
//檢查西元格式
/^\d{4}-\d{2}-\d{2}$/.test("1992-12-22");//true

以上就是常見的正規別達式語法,老實說自己也很少用到這麼多,多半是想到時候才去查一下用法。

這邊跟各位分享一個 橫線區個的字串轉為駝峰式的程式:

var text = "has-a-text";
function upper (match,p1){
    return p1.toUpperCase()
}
text = text.replace(/-(\w)/g,upper);//"hasAText"

參考資料:
忍者 JavaScript 開發技巧探祕
What does regex' flag 'y' do?
Javascript Regular Expressions , 表示法
MDN-正規表達式
[實用] 用 Regular Expression 做字串比對


上一篇
學JS的心路歷程 Day11-函式(六)其餘參數及預設參數
下一篇
學JS的心路歷程 Day13-for of 和 for in
系列文
學JS的心路歷程30

尚未有邦友留言

立即登入留言