使用終端機搜尋特定字串時,大家一定用過 grep 這個指令吧~
但你有想過 grep 為什麼叫 grep 嗎?
沒有的話很正常,因為我也從沒想過,直到在查找正規表達式時意外發現了他的身世
根據無所不知的維基百科:
grep名稱來自於g/re/p(globally search a
regular expression
and print,以正規表示式進行全域尋找以及列印)
看來電腦的世界裡regex真是無所不在呢.....
如果你跟我一樣是regex旱鴨子的話,別怕!這篇文章不會讓你直接進泳池的,我們先在泳池邊踢水就好,暖身好了的話,就開始吧~
在JS中,正規表達式是一個物件,有兩種方式可以建立它。
let pattern = new RegExp('BBQ');
let pattern = /BBQ/;
那要怎麼樣確認一串文字中有我們要的資訊呢?
可以使用RegExp.test(String)
,如果文字中有符合表達式定義好的規則就回傳true,沒有符合就回傳false,先來看個簡單的範例:
註:推薦使用regex101
let pattern = /BBQ/;
/BBQ/.test('I want to eat bbQ.'); // false
/BBQ/.test('BBQ BBQ BBQ.'); //true,但只會比對到第一個符合的
看樣子,正規表達式在意大小寫呢!要改變比對模式的話,可以使用flag
,
這些flag
可以單獨也可以合併使用。
flags
g
: 只要符合的全部找出來,如果沒有設定,找到第一個符合的就停止比對i
: 忽略大小寫m
: 多行文字比對/BBQ/i.test('I want to eat bbQ. hahaha.'); // true
/BBQ/ig.test('BBQ bbQ BBQ.'); // true,全部都會比對到
anchor
上面的例子中,無論BBQ出現在哪個位置都無所謂,但如果要限制文字出現的位置呢?
^
: 匹配字串的開頭$
: 匹配字串的結尾
/^BBQ/.test('I want to eat BBQ.'); // false
/^BBQ/.test('BBQ is yummy.'); //true
/BBQ$/.test('BBQ yo yo yo.'); // false
/BBQ$/.test('We all love BBQ.'); // true
從上面的例子可以知道,就算字串中有符合的文字,如果不在正規表達式指定的位置出現,就不會被比對。
[]
如果不需要完全符合特定文字,只需要字串符合特定範圍呢?
比如說在中秋節發文的時候只要文字中有B和Q,就表示發文者可能很想吃烤肉(?)
/[BQ]/i.test('barbeque is good~'); // true
/BBQ/i.test('barbeque is good~'); // false,沒有用中括號,代表要完全匹配BBQ才回傳true
以下用常使用的範圍做範例:
//輸入必須要有數字
/[0-9]/.test('three two one'); // false
/[0-9]/.test('COVID-19'); // true
//輸入必須含有a-z的字母
/[a-z]/.test('123'); // false
/[a-z]/.test('COVID-19'); //false
/[a-z]/.test('abc'); //true
在前面的指定匹配位置時提到了一個錨點符號^
這個符號如果出現在中括號時,就成了否定字元,概念很像JS中的邏輯運算子NOT!
大概是因為某些範圍在實務上經常使用,所以正規表達式中提供了字元類別來代表這些常用的字串範圍
\d
: 任何的 ASCII 數字,相當於[0-9]
\D
: 任何的 ASCII 數字以外的字元,也可以表示成[^0-9]
\w
: 任何字詞字元,等同於 [A-Za-z0-9]
\W
: 非字詞字元,也可表示成 [^A-Za-z0-9]
\s
: 任何空白字元{}
+
*
當我們需要描述特定規則出現的次數,就得拜託重複字元幫忙了~
{n, m}
let pattern = /\d{2,5}/; -> 代表2到5位數
/\d{2,5}/.test('4'); // flase
/\d{2,5}/.test('1234'); // true
/\d{2,5}/.test('123456'); // 雖然回傳值是true,但只有比對12345,如果要限定只有2到5位數才回傳true,可以使用錨點(如下)
/^\d{2,5}$/.test('123456'); // false
/^\d{2,5}$/.test('423'); // true
{n}
/^\w{3}$/.test('BBQ'); // true
/^\w{3}$/.test('BBQ '); // false, 因為結尾是空白字元
+
/^\d+$/.test(''); // flase
/^\d+$/.test('1'); // true
/^\d+$/.test('42'); // true
/^\d+$/.test('42school'); // false
*
/^\d*$/.test(''); // true
/^\d*$/.test('1'); // true
腳開始抽筋的朋友再撐一下,認識完最後的兩個字元就可以吃烤肉啦~
|
/BBQ|mooncake/.test('pomelo'); //flase
/BBQ|mooncake/.test('BBQ'); // true
/BBQ|mooncake/.test('mooncake'); //true
(...)
根據JS大全,括弧有數個用途,其中之一是把不同的項目歸組成一個子表達式,可以想成是一個個單元。我們實際看圖比較清楚。
首先我們先定義規則為開頭是四個數字,後面需緊跟著字詞字元,測試的字串分別為5252BBQ和777lucky。
可以看到右側的比對資訊欄中除了配對的字串外,還包含群組資訊,如果我們把規則中的括弧拿掉,就只出現比對的完整資料而已。
回到昨天還看不懂的魔法咒語 /^(a |an |the )/i
是不是好像沒那麼困難了呢,如果還是看不懂的話沒關係,先吃一波烤肉再說
正規表示式 - 維基百科
grep - 維基百科
A quick and simple guide to JavaScript Regular Expressions
JavaScript大全 第七版