【重溫基礎】9.正則表達式

本文是 重溫基礎 系列文章的第九篇。
今日感覺:時間管理-角色管理法。前端

系列目錄:git

本章節複習的是JS中的正則表達式,JS中用來匹配字符串的強大工具。github

前置知識:
JS中的正則表達式是用來匹配字符串中指定字符組合的模式。
另外須要記住:正則表達式也是對象。正則表達式

1.建立正則表達式

  • 使用一個正則表達式字面量:
let reg = /ab+c/;
let reg = /^[a-zA-z]/gi;
複製代碼
  • 使用RegExp對象:
    new RegExp(str[, attr])接收2個參數,str是一個字符串,指定正則表達式匹配規則,attr可選,表示匹配模式,值有g(全局匹配),i(區分大小寫的匹配)和m(多行匹配)。
let reg = new RegExp('ab+c');
let reg = new RegExp(/^[a-zA-z]/, "gi");
let reg = new RegExp("^[a-zA-z]", "gi");
複製代碼

正則表達式的返回值,是一個新的RegExp對象,具備指定的模式和標誌。
返回信息介紹數組

對象 屬性 描述 案例中對應的值
reg lastIndex 下一個匹配的索引(僅在使用g參數時可用) 0
reg source 模式文本。在正則表達式建立時更新,不執行。 "ab+c"
reg ignoreCase 是否使用了 "i" 標記使正則匹配忽略大小寫。 true
reg global 是否使用了 "g" 標記來進行全局的匹配。 true
reg multiline 是否使用了 "m" 標記使正則工做在多行模式。 false

關於正則表達式的一些方法屬性,文章後面介紹,這裏先複習定義和使用微信

2.使用正則表達式

JS的正則表達式能夠被用於:ide

  • RegExp對象的exectest方法;
  • String對象的matchreplacesearchsplit方法。

2.1 RegExp對象方法

方法 介紹
exec 檢索字符串中指定的值。返回找到的值,並肯定其位置。
test 檢索字符串中指定的值。返回 truefalse

2.1.1 exec(str)

str: 須要檢索的字符串。
若檢索成功,返回匹配的數組,不然返回null。函數

let str = "hello leo!";
let reg = new RegExp("leo", "g");
let result = reg.exec(str);
// 也能夠寫成
let result = /leo/g.exec("hello leo!");

/* [ 0: "leo", groups: undefined, index: 6, input: "hello leo!", length: 1 ] */

let result2 = /(leo \S)/g.exec("hello leo hi leo!");
/* 0: "leo hi" 1: "leo hi" 2: "hi" groups: undefined index: 6 input: "hello leo hi leo!" length: 3 */
複製代碼

返回信息介紹工具

對象 屬性 描述 案例中對應的值
result [0] 匹配到的全部字符串 "leo"
result input 初始字符串。 "hello leo!"
result index 在輸入的字符串中匹配到的以0開始的索引值。 6
result2 [1],...,[n] 括號中的分組捕獲 [1]=> "leo hi";[2] => "hi"

2.1.2 test(str)

str:須要檢索的字符串。
若匹配成功返回true不然false
等價於 reg.exec(str) != nullpost

let str = "hello leo!";
let res = /^leo/.test(str);   // fasle
let res1 = /^leo/.test(str);  // true
複製代碼

^str表示匹配以str開頭的字符串,這些符號文章後面會介紹。

2.2 String對象方法

方法 介紹
search 檢索與正則表達式相匹配的值。
match 找到一個或多個正則表達式的匹配。
replace 替換與正則表達式匹配的子串。
split 把字符串分割爲字符串數組。

2.2.1 search

str.search(reg)
str:被檢索的源字符串。
reg:能夠是須要檢索的字符串,也能夠是須要檢索的RegExp對象,能夠添加標誌,如i

若檢索成功,返回第一個RegExp對象匹配的字符串的起始位置,不然返回-1

let str = "hello leo!";
let res = str.search(/leo/g);  // 6

let str1 = "hello leoleoleoleo!";
let res1 = str.search(/leo/g); // 6
let res2 = str.search(/pingan/g); // -1
複製代碼

2.2.2 match

str.match(reg)
str:被檢索的源字符串。
reg:能夠是須要檢索的字符串,也能夠是須要檢索的RegExp對象,能夠添加標誌,如i

若檢索成功,返回與reg匹配的全部結果的一個數組,數組的第一項是進行匹配完整的字符串,以後的項是用圓括號捕獲的結果,不然返回null

let str = 'For more information, see Chapter 3.4.5.1';
let reg = /see (chapter \d+(\.\d)*)/i;
let result = str.match(reg);
/* logs [ 'see Chapter 3.4.5.1', 'Chapter 3.4.5.1', '.1', index: 22, input: 'For more information, see Chapter 3.4.5.1' ] */
複製代碼

'see Chapter 3.4.5.1' 是整個匹配。
'Chapter 3.4.5.1''(chapter \d+(\.\d)*)'捕獲。
'.1' 是被'(\.\d)'捕獲的最後一個值。
'index' 屬性(22)是整個匹配從零開始的索引。
'input' 屬性是被解析的原始字符串。

2.2.3 replace

將字符串中指定字符替換成其餘字符,或替換成一個與正則表達式匹配的字符串。
str.replace(sub/reg,val):

  • str: 源字符串
  • sub: 使用字符串來檢索被替換的文本
  • reg: 使用RegExp對象來檢索來檢索被替換的文本
  • val: 指定替換文本
    返回替換成功以後的字符串,不改變源字符串內容。
let str = "hello leo!";
let res = str.replace('leo','pingan');//"hello pingan!"
複製代碼

val可使用特殊變量名

變量名 表明的值
$$ 插入一個 "$"。
$& 插入匹配的子串。
$ 插入當前匹配的子串左邊的內容。
$' 插入當前匹配的子串右邊的內容。
$n 假如第一個參數是 RegExp對象,而且 n 是個小於100的非負整數,那麼插入第 n 個括號匹配的字符串。提示:索引是從1開始
let str = "hello leo!";
let res = str.replace(/(\w+)\s* \s*(\w+)/, "$2:$1");
// "leo:hello!"
複製代碼

2.2.4 split

將一個字符串,按照指定符號分割成一個字符串數組。
str.split(sub[, maxlength]):

  • str: 源字符串
  • sub: 指定的分割符號或正則
  • maxlength: 源字符串
let str = "hello leo!";
let res = str.split();   //["hello leo!"]
let res = str.split(""); //["h", "e", "l", "l", "o", " ", "l", "e", "o", "!"]
let res = str.split(" ");//["hello", "leo!"]
let res = str.split(/\s+/);//["hello", "leo!"]

let res = str.split("",3);//["h", "e", "l"]
複製代碼

2.3 使用狀況

  • 當咱們想要查找一個字符串中的一個匹配是否找到,能夠用testsearch方法。
  • 當咱們想要獲得匹配的更多信息,咱們就須要用到execmatch方法。

3.正則表達式符號介紹

詳細的每一個符號的用法,能夠查閱 W3school JavaScript RegExp 對象

3.1 修飾符

修飾符 描述
i 執行對大小寫不敏感的匹配。
g 執行全局匹配(查找全部匹配而非在找到第一個匹配後中止)。
m 執行多行匹配。
let str = "hello leo!"
let res = /Leo/i.test(str); // i 不區分大小寫 因此返回true
let res = /Leo/.test(str);  // fasle
複製代碼

3.2 方括號

用於查找指定返回以內的字符:

表達式 描述
[abc] 查找方括號之間的任何字符。
[^abc] 查找任何不在方括號之間的字符。
[0-9] 查找任何從 0 至 9 的數字。
[a-z] 查找任何從小寫 a 到小寫 z 的字符。
[A-Z] 查找任何從大寫 A 到大寫 Z 的字符。
[A-z] 查找任何從大寫 A 到小寫 z 的字符。
[adgk] 查找給定集合內的任何字符。
[^adgk] 查找給定集合外的任何字符。
(red) 查找任何指定的選項。
let str = "hello leo!";
let res = str.match(/[a-m]/g);
//["h", "e", "l", "l", "l", "e"]
let res = str.match(/[^a-m]/g);
//["o", " ", "o", "!"]
複製代碼

3.3 元字符

元字符是擁有特殊含義的字符:

元字符 描述
. 查找單個字符,除了換行和行結束符。
\w 查找單詞字符。
\W 查找非單詞字符。
\d 查找數字。
\D 查找非數字字符。
\s 查找空白字符。
\S 查找非空白字符。
\b 匹配單詞邊界。
\B 匹配非單詞邊界。
\0 查找 NUL 字符。
\n 查找換行符。
\f 查找換頁符。
\r 查找回車符。
\t 查找製表符。
\v 查找垂直製表符。
\xxx 查找以八進制數 xxx 規定的字符。
\xdd 查找以十六進制數 dd 規定的字符。
\uxxxx 查找以十六進制數 xxxx 規定的 Unicode 字符。
let str = "hello leo hi pingan!";
let res = str.match(/o\s/g);
//["o ", "o "]
let res = str.match(/\s/g);
//[" ", " ", " "]
複製代碼

3.4 量詞

量詞 描述
n+ 匹配任何包含至少一個 n 的字符串。
n* 匹配任何包含零個或多個 n 的字符串。
n? 匹配任何包含零個或一個 n 的字符串。
n{X} 匹配包含 X 個 n 的序列的字符串。
n{X,Y} 匹配包含 X 至 Y 個 n 的序列的字符串。
n{X,} 匹配包含至少 X 個 n 的序列的字符串。
n$ 匹配任何結尾爲 n 的字符串。
^n 匹配任何開頭爲 n 的字符串。
?=n 匹配任何其後緊接指定字符串 n 的字符串。
?!n 匹配任何其後沒有緊接指定字符串 n 的字符串。
let str = "hello leo!";
let res = str.match(/^hello/g);
// ["hello"]
let res = str.match(/^pingan/g);
//null

複製代碼

4. 正則表達式拓展(ES6)

4.1 介紹

在ES5中有兩種狀況。

  • 參數是字符串,則第二個參數爲正則表達式的修飾符。
let a = new RegExp('abc', 'i');
// 等價於
let a = /abx/i;
複製代碼
  • 參數是正則表達式,返回一個原表達式的拷貝,且不能有第二個參數,不然報錯。
let a = new RegExp(/abc/i);
//等價於
let a = /abx/i;

let a = new RegExp(/abc/, 'i');
// Uncaught TypeError
複製代碼

ES6中使用:
第一個參數是正則對象,第二個是指定修飾符,若是第一個參數已經有修飾符,則會被第二個參數覆蓋。

new RegExp(/abc/ig, 'i');
複製代碼

4.2 字符串的正則方法

經常使用的四種方法:match()replace()search()split()

4.3 u修飾符

添加u修飾符,是爲了處理大於uFFFF的Unicode字符,即正確處理四個字節的UTF-16編碼。

/^\uD83D/u.test('\uD83D\uDC2A'); // false
/^\uD83D/.test('\uD83D\uDC2A');  // true
複製代碼

因爲ES5以前不支持四個字節UTF-16編碼,會識別爲兩個字符,致使第二行輸出true,加入u修飾符後ES6就會識別爲一個字符,因此輸出false

注意:
加上u修飾符後,會改變下面正則表達式的行爲:

  • (1)點字符 點字符(.)在正則中表示除了換行符之外的任意單個字符。對於碼點大於0xFFFF的Unicode字符,點字符不能識別,必須加上u修飾符。
var a = "𠮷";
/^.$/.test(a);  // false
/^.$/u.test(a); // true
複製代碼
  • (2)Unicode字符表示法 使用ES6新增的大括號表示Unicode字符時,必須在表達式添加u修飾符,才能識別大括號。
/\u{61}/.test('a');      // false
/\u{61}/u.test('a');     // true
/\u{20BB7}/u.test('𠮷'); // true
複製代碼
  • (3)量詞 使用u修飾符後,全部量詞都會正確識別碼點大於0xFFFF的 Unicode 字符。
/a{2}/.test('aa');    // true
/a{2}/u.test('aa');   // true
/𠮷{2}/.test('𠮷𠮷');  // false
/𠮷{2}/u.test('𠮷𠮷'); // true
複製代碼
  • (4)i修飾符 不加u修飾符,就沒法識別非規範的K字符。
/[a-z]/i.test('\u212A') // false
/[a-z]/iu.test('\u212A') // true
複製代碼

檢查是否設置u修飾符: 使用unicode屬性。

const a = /hello/;
const b = /hello/u;

a.unicode // false
b.unicode // true
複製代碼

4.4 y修飾符

y修飾符與g修飾符相似,也是全局匹配,後一次匹配都是從上一次匹配成功的下一個位置開始。區別在於,g修飾符只要剩餘位置中存在匹配便可,而y修飾符是必須從剩餘第一個開始。

var s = 'aaa_aa_a';
var r1 = /a+/g;
var r2 = /a+/y;

r1.exec(s) // ["aaa"]
r2.exec(s) // ["aaa"]

r1.exec(s) // ["aa"] 剩餘 '_aa_a'
r2.exec(s) // null
複製代碼

lastIndex屬性: 指定匹配的開始位置:

const a = /a/y;
a.lastIndex = 2;  // 從2號位置開始匹配
a.exec('wahaha'); // null
a.lastIndex = 3;  // 從3號位置開始匹配
let c = a.exec('wahaha');
c.index;          // 3
a.lastIndex;      // 4
複製代碼

返回多個匹配
一個y修飾符對match方法只能返回第一個匹配,與g修飾符搭配能返回全部匹配。

'a1a2a3'.match(/a\d/y);  // ["a1"]
'a1a2a3'.match(/a\d/gy); // ["a1", "a2", "a3"]
複製代碼

檢查是否使用y修飾符
使用sticky屬性檢查。

const a = /hello\d/y;
a.sticky;     // true
複製代碼

4.5 flags屬性

flags屬性返回全部正則表達式的修飾符。

/abc/ig.flags;  // 'gi'
複製代碼

5. 正則表達式拓展(ES9)

在正則表達式中,點(.)能夠表示任意單個字符,除了兩個:用u修飾符解決四個字節的UTF-16字符,另外一個是行終止符。
終止符即表示一行的結束,以下四個字符屬於「行終止符」:

  • U+000A 換行符(\n)
  • U+000D 回車符(\r)
  • U+2028 行分隔符(line separator)
  • U+2029 段分隔符(paragraph separator)
/foo.bar/.test('foo\nbar')
// false
複製代碼

上面代碼中,由於.不匹配\n,因此正則表達式返回false
換個醒,能夠匹配任意單個字符:

/foo[^]bar/.test('foo\nbar')
// true
複製代碼

ES9引入s修飾符,使得.能夠匹配任意單個字符:

/foo.bar/s.test('foo\nbar') // true
複製代碼

這被稱爲dotAll模式,即點(dot)表明一切字符。因此,正則表達式還引入了一個dotAll屬性,返回一個布爾值,表示該正則表達式是否處在dotAll模式。

const re = /foo.bar/s;
// 另外一種寫法
// const re = new RegExp('foo.bar', 's');

re.test('foo\nbar') // true
re.dotAll // true
re.flags // 's'
複製代碼

/s修飾符和多行修飾符/m不衝突,二者一塊兒使用的狀況下,.匹配全部字符,而^$匹配每一行的行首和行尾。

參考資料

1.MDN 正則表達式
2.W3school JavaScript RegExp 對象


本部份內容到這結束

Author 王平安
E-mail pingan8787@qq.com
博 客 www.pingan8787.com
微 信 pingan8787
每日文章推薦 github.com/pingan8787/…
JS小冊 js.pingan8787.com

歡迎關注個人微信公衆號【前端自習課】

相關文章
相關標籤/搜索