Date: Nov. 17th, 2019
Lecturer: Chia
正規表達式
被用來匹配字串中字元組合的模式。
一個描述字串資料之模式(patterns)的方式。
let animalCount = /\b\d+ (pig|cow|chicken)s?\b/;
console.log(animalCount.test("15 pigs"));
// → true
console.log(animalCount.test("15 pigchickens"));
// → false
// (方式一) 使用 RegExp()
let re1 = new RegExp("abc");
// (方式二) 使用 正斜杠 / 包覆所描述的模式
let re2 = /abc/;
若 ? 和 + 的前面添加反斜線 \,代表將之當成一般字元,
意即表示字元本身,沒有特殊用途。
let eighteenPlus = /eighteen\+/;
// + 原本是特殊字元,但這裡要當成非特殊字元
console.log(/abc/.test("abcde"));
// → true
console.log(/abc/.test("abxde"));
// → false
console.log(/[0123456789]/.test("in 1992"));
// → true
console.log(/[0-9]/.test("in 1992"));
// → true
若將一組字符放在 [ ] 內,表示匹配[ ]內的所有字符。
意即只要符合 [ ] 內所列出的字符,就算匹配成功。
特殊字元 | 解說 |
---|---|
\d | 任何數字 |
\w | 任何字母和數字(“文字字符”) |
\s | 任何空白字符(space, tab, newline… |
\D | 非數字的字符 |
\W | 非字母和數字字符 |
\S | 非空白字符 |
. | 除換行字符以外的任何單一字元。 |
let dateTime = /\d\d-\d\d-\d\d\d\d \d\d:\d\d/;
console.log(dateTime.test("01-30-2003 15:20"));
console.log(dateTime.test("30-jan-2003 15:20"));
let notBinary = /[^01]/;
console.log(notBinary.test("1100100010100110"));
// → false
console.log(notBinary.test("1100100010200110"));
// → true 1100100010`2`00110
console.log(/'\d+'/.test("'123'"));
console.log(/'\d+'/.test("''"));
console.log(/'\d*'/.test("'123'"));
console.log(/'\d*'/.test("''"));
+ | 該字符重複出現至少1次 |
---|---|
* | 該字符重複出現0次以上 |
? | 該字符重複出現出現0次或1次 |
let neighbor = /neighbou?r/;
console.log(neighbor.test("neighbour"));
console.log(neighbor.test("neighbor"));
let dateTime = /\d{1,2}-\d{1,2}-\d{4} \d{1,2}:\d{2}/;
console.log(dateTime.test("1-30-2003 8:45"));
// → true
{4} | 該字符需出現4次,即符合。 |
---|---|
{2,4} | 該字符出現至少2次、最多4次,即符合。 |
{5,} | 該字符出現至少5次,即符合。(開放式範圍) |
let cartoonCrying = /boo+(hok+)+/i;
console.log(cartoonCrying.test("BoohoooohooHooo"));
console.log(cartoonCrying.test("Boohokoohokhook"));
>>> `i`是指`不區分大小寫`
let match = /\d+/.exec("one two 100");
console.log(match);
// → ["100"]
console.log(match.index);
// → 8
console.log("one two 100".match(/\d+/));
console.log("one two 100".match(/\d?/));
console.log("one two 100".match(/\d*/));
let quotedText = /'([^']*)'/;
// '([^']*)' -> 字串外面使用''包裹。群組裡面沒有`'`出現0次以上。
// 'hello' or hello
console.log(quotedText.exec("she said 'hello'"));
// → ["'hello'", "hello"]
const regexp = /(\w+)\.jpg/;
console.log(regexp.exec('File name: cat.jpg'));
// ["cat.jpg", "cat"]
console.log(/bad(ly)?/.exec("bad"));
// → ["bad", undefined]
// 先比對 bad(ly)? 再比對 (ly)?
console.log(/bad(ly)?/.exec("badl"));
console.log(/bad(ly)?/.exec("badlyr"));
console.log(/(\d)+/.exec("123")); // (\d)+
// → ["123", "3"]
console.log(new Date());
// → Tue Nov 12 2019 10:28:37 GMT+0800 (台北標準時間)
Date 物件提供 getFullYear(), getMonth(), getDate(), getHours(), getMinutes(), and getSeconds()方法。
console.log(new Date(2019, 11, 12));
// → Thu Dec 12 2019 00:00:00 GMT+0800 (台北標準時間)
console.log(new Date(2009, 11, 12, 12, 59, 59, 999));
// 最後的四個參數為(小時,分鐘,秒和毫秒),預設皆為0。
console.log(new Date(2019, 10, 12).getTime());
// → 1573488000000
console.log(Date.now());
// → 1573527038896
console.log(new Date(1573527038896));
// → Tue Nov 12 2019 10:50:38 GMT+0800 (台北標準時間)
getTime()方法,可回傳從1970年至某個時間點的毫秒數。
function processDate(string) {
let [_, month, day, year] = /(\d{1,2})-(\d{1,2})-(\d{4})/.exec(string);
// 底線 _ (underscore) 忽略,用於跳過由exec返回的陣列中匹配的物件。
return new Date(year, month - 1, day);
}
console.log(processDate("testing: 1-30-2003 in javascript."));
// → Thu Jan 30 2003 00:00:00 GMT+0800 (台北標準時間)
備註:(匹配模式不夠嚴謹,於下一節 "單詞和字串的邊界" 說明)
console.log(processDate("100-1-30000")); // 匹配 "00-1-3000"
>>> Sun Dec 01 2999 00:00:00 GMT+0800 (台北標準時間)
^ | 匹配字串的開頭 |
---|---|
$ | 匹配字串的結尾 |
/^\d+$/ | 匹配開頭包含至少一個數字的字串 匹配結尾包含至少一個數字的字串 |
---|---|
/^!/ | 匹配開頭為!的字串 |
\b | 配對 word boundary(單詞邊界)。 單詞邊界是指一個字元的前後沒有其他字元。 |
---|
let matchedResult = 'This is an apple.'.match(/\bis\b/);
// is 這個單字才會被選到
// This 中的 is 不會被選到,因為前有其他字元。
// [ 'is', index: 5, input: 'This is an apple.' ]
console.log(/cat/.test("concatenate"));
console.log(/\bcat\b/.test("concatenate"));
console.log(/\bcat/.test("catenate"));
| | 在左側模式和右側模式之間進行選擇。 (一次匹配多種可選擇的類型) |
---|
let animalCount = /\b\d+ (pig|cow|chicken)s?\b/;
console.log(animalCount.test("15 pigs"));
// → true
console.log(animalCount.test("15 pigchickens"));
// → false
let animalCount = /\b\d+ (pig|cow|chicken)s?\b/;
console.log(animalCount.test("the 3 pigs"));
// → true
let reg = /\b([01]+b|[\da-f]+h|\d+)\b/;
console.log(reg.test("0 856 fr2 eah 1b"));
// → true
console.log(reg.exec("0m 856 fr2 eah 1b")); // 856 eah 1b 皆符合
// → ["856", "856"]
let reg = /^.*x/;
console.log(reg.test("."));
console.log(reg.test(""));
console.log(reg.test("x"));
console.log(reg.test(".x"));
console.log(reg.test(".xa"));
console.log(reg.test("abcxe"));
let reg = /([01]+)+b/;
console.log(reg.test("01 123"));
console.log(reg.test("0 reg"));
console.log(reg.test("01b 123"));
console.log(reg.test("0b reg"));
console.log("papa".replace("p", "m"));
// → mapa
console.log("Borobudur".replace(/[ou]/, "j"));
// → Bjrobudur
console.log("Borobudur".replace(/[ou]/g, "j"));
// → Bjrjbjdjr
console.log(
"Liskov, Barbara\nMcCarthy, John\nWadler, Philip"
.replace(/(\w+), (\w+)/g, "$2 $1"));
// → Barbara Liskov
// John McCarthy
// Philip Wadler
console.log(
"Liskov, Barbara\nMcCarthy, John\nWadler, Philip"
.replace(/(\w+), (\w+)/g, "$&")); // $& 指的是所有括號( )的內容
// → Liskov, Barbara
// McCarthy, John
// Wadler, Philip
let html = `
<table>
<td>aaa</td>
</table>
<table>
<td>bbb</td>
</table>
`;
let reg = /<table[.\n\s\S]*<\/table>/g;
let r = html.match(reg);
console.log(r);
// let html 同上
let reg = /<table[.\n\s\S]*?<\/table>/g;
let r = html.match(reg);
console.log(r);
使用「脫逸字元\」
// 使用 RegExp()
let pp2 = new RegExp("ab\/nc");
// 使用 正斜杠 / 包覆所描述的模式
let pp1 = /ab\/nc/;
欲將特殊字元,轉為一般字串
使用「脫逸字元\」
let pp1 = /ab\/nc/;
let str1 = "qaz1ab/nc";
console.log(pp1.exec(str1));
let pp2 = new RegExp("ab\/nc");
let str2 = "qaz1ab/nc";
console.log(pp2.exec(str2));
正規表達式固定已知!
let name = "harry"; // 把 harry 當成模式
let text = "Harry is a suspicious character.";
let regexp = new RegExp("\\b(" + name + ")\\b", "gi");
// 符合模式
console.log(text.replace(regexp, "_$1_"));
// → _Harry_ is a suspicious character.
正規表達式動態未知!
let str="Hello world!";
console.log(str.indexOf("Hello"));
console.log(str.indexOf("World"));
console.log(str.indexOf("world"));
Output:
0
-1
6
let str="Mr. Blue has a blue house";
console.log(str.search(/blue/i));
console.log(" word".search(/\S/)); //012
// → 2
let str = "a0bc1";
// Indexes: 01234
let rexWithout = /\d/;
//指定位子搜尋,對它沒用。從index=0開始搜尋
rexWithout.lastIndex = 2;
console.log(rexWithout.exec(str));
// → [ '0', index: 1, input: 'a0bc1', groups: undefined ]
let rexWithout_g = /\d/g;
//指定位子搜尋,對它有用。從index=2開始搜尋,會繼續往後搜尋
rexWithout_g.lastIndex = 2;
console.log(rexWithout_g.exec(str));
// → [ '1', index: 4, input: 'a0bc1', groups: undefined ]
let str = "a0bc1";
// Indexes: 01234
let rexWith_y = /\d/y;
rexWith_y.lastIndex = 2;
//指定位子搜尋,對它有用。只搜尋index=2,"不會"繼續往後搜尋
console.log(rexWith_y.exec(str));
// → null
let str = "a0bc1";
// Indexes: 01234
let rexWith_y = /\d/y;
rexWith_y.lastIndex = 1;
console.log(rexWith_y.exec(str));
rexWith_y.lastIndex = 4;
console.log(rexWith_y.exec(str));
console.log("Banana".match(/an/g));
// → ["an", "an"]
searchengine=https://duckduckgo.com/?q=$1
spitefulness=9.7
; comments are preceded by a semicolon...
; each section concerns an individual enemy
[larry]
fullname=Larry Doe
type=kindergarten bully
website=http://www.geocities.com/CapeCanaveral/11451
[davaeorn]
fullname=Davaeorn
type=evil wizard
outputdir=/home/marijn/enemies/davaeorn
\r | 返回符號(返回同一行的開頭,不前進到下一行) |
---|---|
\n | 換行符號 |
/\r?\n/ | 允許行與行之間為\n或\r\n的拆分方式。 |
function parseINI(string) {
let result = {};
let section = result;
string.split(/\r?\n/).forEach(line => {
let match;
if (match = line.match(/^(\w+)=(.*)$/)) {
//是屬性
section[match[1]] = match[2];
} else if (match = line.match(/^\[(.*)\]$/)) {
//是節標題
section = result[match[1]] = {};
} else if (!/^\s*(;.*)?$/.test(line)) {
//不是節標題或屬性
// 檢查它是註釋還是空行 // (;.*) 匹配註釋 ? 匹配空格
throw new Error("Line '" + line + "' is not valid.");
// 與任何形式都不匹配時,引發異常。
}
});
return result;
}
console.log(parseINI(`
name=Vasilis
[address]
city=Tessaloniki`));
// → {name: "Vasilis", address: {city: "Tessaloniki"}}
console.log(/🍎{3}/.test("🍎🍎🍎"));
// → false
console.log(/<.>/.test("<🌹>"));
// → false
console.log(/<.>/u.test("<🌹>"));
// 必須在正則表達式中添加`u`,以Unicode使其正確處理此類字符。
// → true
/* \p{Property=Value} */
console.log(/\p{Script=Greek}/u.test("α"));
// → true
console.log(/\p{Script=Arabic}/u.test("α"));
// → false
/* \p{Name} */
console.log(/\p{Alphabetic}/u.test("α"));
// → true
console.log(/\p{Alphabetic}/u.test("!"));
// → false