今天我們來看正規表達式,在談到為什麼需要多學這個之前,先來看個範例。
假設需要判斷輸入字串是否含有"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
是不是比上面的例子乾淨許多了呢!
既然這樣,話不多說我們趕緊來看到底怎麼用吧。
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 | 任何空白字元(空格、Tab及換頁),等於 [ \f\n\r\t\v] |
\S | 空白字元之外的其他字元,等於 [^ \f\n\r\t\v] |
//檢查西元格式
/^\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 做字串比對