最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

JavaScript正則表達(dá)式之選擇、分組與引用深度解析

 更新時(shí)間:2026年01月06日 11:33:09   作者:愛吃甜品的糯米團(tuán)子  
正則表達(dá)式是非常重要的技術(shù),它不僅僅只局限于java語言,不管是任何一種成型的語言,都會(huì)有正則,這篇文章主要介紹了JavaScript正則表達(dá)式之選擇、分組與引用的相關(guān)資料,需要的朋友可以參考下

在正則表達(dá)式中,“選擇、分組、引用” 是實(shí)現(xiàn)復(fù)雜匹配邏輯的核心語法,能夠?qū)⒍鄠€(gè)簡單規(guī)則組合成靈活的匹配模板。

一、選擇(|):實(shí)現(xiàn) “或” 邏輯匹配

選擇符(|)用于匹配 “多個(gè)模式中的任意一個(gè)”,相當(dāng)于邏輯中的 “或”(OR),是正則中實(shí)現(xiàn)多規(guī)則匹配的基礎(chǔ)。

1. 核心定義

選擇符 | 分隔兩個(gè)或多個(gè)候選模式,正則會(huì)依次嘗試匹配每個(gè)模式,只要有一個(gè)模式匹配成功,整個(gè)正則就返回匹配結(jié)果。

2. 語法規(guī)則

  • 基礎(chǔ)語法:pattern1|pattern2|pattern3(匹配 pattern1、pattern2、pattern3 中的任意一個(gè));
  • 優(yōu)先級(jí):| 的優(yōu)先級(jí)最低,若需限定選擇范圍,需配合分組 () 使用(否則會(huì)匹配 “左側(cè)全量 + 右側(cè)全量”);
  • 匹配順序:正則會(huì)從左到右嘗試候選模式,一旦匹配成功就停止后續(xù)嘗試(即 “左優(yōu)先匹配”)。

3. 代碼案例與運(yùn)行結(jié)果

案例 1:基礎(chǔ)選擇匹配(匹配多個(gè)固定字符串)

javascript

運(yùn)行

// 匹配 "apple"、"banana"、"orange" 中的任意一個(gè)
const reg = /apple|banana|orange/;
const fruits = ["apple", "banana", "orange", "grape"];

fruits.forEach(fruit => {
  console.log(`${fruit}: ${reg.test(fruit)}`);
});
// 運(yùn)行結(jié)果:
// apple: true(匹配 "apple")
// banana: true(匹配 "banana")
// orange: true(匹配 "orange")
// grape: false(無匹配)

案例 2:選擇符與分組配合(限定選擇范圍)

若不使用分組,選擇符會(huì)匹配 “左側(cè)全量 + 右側(cè)全量”,導(dǎo)致邏輯錯(cuò)誤,需用 () 限定選擇范圍:

javascript

運(yùn)行

const str1 = "I like apples";
const str2 = "I like oranges";
const str3 = "I like grape";

// 錯(cuò)誤寫法:未分組,匹配 "I like app" 或 "les"(邏輯不符合預(yù)期)
const wrongReg = /I like app|les/;
console.log(wrongReg.test(str1)); // true(錯(cuò)誤匹配 "I like app")
console.log(wrongReg.test(str2)); // false(無匹配)

// 正確寫法:用 () 限定選擇范圍,匹配 "I like apple" 或 "I like orange"
const rightReg = /I like (apple|orange)/;
console.log(rightReg.test(str1)); // true(匹配 "I like apple")
console.log(rightReg.test(str2)); // true(匹配 "I like orange")
console.log(rightReg.test(str3)); // false(無匹配)

案例 3:選擇符的左優(yōu)先匹配特性

正則會(huì)從左到右嘗試候選模式,一旦匹配成功就停止,即使右側(cè)有更優(yōu)匹配:

javascript

運(yùn)行

// 匹配 "abc" 或 "abcd"(左優(yōu)先:先嘗試 "abc")
const reg = /abc|abcd/;
const str = "abcd";

// 匹配結(jié)果:優(yōu)先匹配左側(cè)的 "abc",而非完整的 "abcd"
console.log(str.match(reg)); // ["abc", index: 0, input: "abcd", groups: undefined]

4. 實(shí)戰(zhàn)場景:匹配多種日期格式

用選擇符匹配 yyyy-mm-dd、yyyy/mm/ddyyyy.mm.dd 三種日期格式:

javascript

運(yùn)行

// 匹配三種日期格式(年-月-日、年/月/日、年.月.日)
const dateReg = /^\d{4}(-|\/|\.)\d{2}\1\d{2}$/; 
// 注:\1 是分組引用,后續(xù)會(huì)講解,此處用于保證分隔符一致(如 "-" 前后一致)

console.log(dateReg.test("2024-05-20")); // true(匹配 "-" 格式)
console.log(dateReg.test("2024/05/20")); // true(匹配 "/" 格式)
console.log(dateReg.test("2024.05.20")); // true(匹配 "." 格式)
console.log(dateReg.test("2024-05/20")); // false(分隔符不一致)

二、分組(()):將多個(gè)字符視為一個(gè)整體

分組符(())用于將多個(gè)字符或子模式 “打包” 成一個(gè)整體,實(shí)現(xiàn) “批量控制”(如批量限定量詞、批量參與選擇),是正則中實(shí)現(xiàn)復(fù)雜規(guī)則的核心。

1. 核心定義

分組符 () 會(huì)將括號(hào)內(nèi)的內(nèi)容視為一個(gè) “子模式”,可以對(duì)這個(gè)子模式整體應(yīng)用量詞、選擇符等規(guī)則,同時(shí)分組會(huì)捕獲匹配結(jié)果(用于后續(xù)引用)。

2. 分組的分類與語法

根據(jù)是否捕獲匹配結(jié)果,分組可分為 “捕獲組” 和 “非捕獲組”,常用分類如下:

分組類型語法描述
普通捕獲組(pattern)捕獲括號(hào)內(nèi) pattern 的匹配結(jié)果,可通過 \n(正則內(nèi))或 result[n](代碼內(nèi))引用
非捕獲組(?:pattern)僅將 pattern 視為整體,不捕獲匹配結(jié)果(節(jié)省性能,無需引用時(shí)推薦)
正向前瞻分組(?=pattern)不捕獲結(jié)果,僅判斷當(dāng)前位置后是否滿足 pattern(前面文章已講,此處不展開)
負(fù)向前瞻分組(?!pattern)不捕獲結(jié)果,僅判斷當(dāng)前位置后是否不滿足 pattern

3. 代碼案例與運(yùn)行結(jié)果

案例 1:普通捕獲組(批量限定量詞)

將 ab 視為一個(gè)整體,匹配其重復(fù) 2 次的場景:

javascript

運(yùn)行

// 分組前:匹配 "a" 重復(fù) 2 次 + "b"(即 "aab")
const noGroupReg = /a{2}b/;
// 分組后:匹配 "ab" 重復(fù) 2 次(即 "abab")
const groupReg = /(ab){2}/;

console.log(noGroupReg.test("aab")); // true(分組前,匹配 "aab")
console.log(noGroupReg.test("abab")); // false(分組前,不匹配)
console.log(groupReg.test("abab")); // true(分組后,匹配 "abab")
console.log(groupReg.test("aab")); // false(分組后,不匹配)

案例 2:非捕獲組(僅整體控制,不捕獲結(jié)果)

當(dāng)不需要引用分組結(jié)果時(shí),用 (?:pattern) 定義非捕獲組,避免不必要的結(jié)果存儲(chǔ),提升性能:

javascript

運(yùn)行

// 非捕獲組:匹配 "apple" 或 "banana",不捕獲結(jié)果
const nonCaptureReg = /(?:apple|banana)/;
const str = "I like apple";

// 匹配結(jié)果:僅返回整體匹配內(nèi)容,無分組捕獲結(jié)果
const result = str.match(nonCaptureReg);
console.log(result); // ["apple", index: 7, input: "I like apple", groups: undefined]
console.log(result[1]); // undefined(非捕獲組,無分組結(jié)果)

// 普通捕獲組:捕獲 "apple" 或 "banana" 的結(jié)果
const captureReg = /(apple|banana)/;
const captureResult = str.match(captureReg);
console.log(captureResult[1]); // "apple"(普通捕獲組,可獲取分組結(jié)果)

案例 3:分組嵌套(復(fù)雜子模式控制)

分組支持嵌套,嵌套分組的捕獲順序?yàn)?“左括號(hào)出現(xiàn)的順序”(即第 1 個(gè)左括號(hào)為組 1,第 2 個(gè)為組 2,以此類推):

javascript

運(yùn)行

// 嵌套分組:匹配 "a(bc(d))"(組 1:"bc(d)",組 2:"d")
const reg = /a(bc(d))/;
const str = "abcde";
const result = reg.exec(str);

console.log(result[0]); // "abcd"(整體匹配結(jié)果)
console.log(result[1]); // "bcd"(第 1 個(gè)左括號(hào)對(duì)應(yīng)的分組結(jié)果)
console.log(result[2]); // "d"(第 2 個(gè)左括號(hào)對(duì)應(yīng)的分組結(jié)果)

4. 實(shí)戰(zhàn)場景:提取 URL 中的域名和路徑

用分組提取 URL(如 https://www.baidu.com/s?wd=regex)中的 “域名”(www.baidu.com)和 “路徑”(/s):

javascript

運(yùn)行

function extractUrlParts(url) {
  // 分組1:域名(如 www.baidu.com),分組2:路徑(如 /s)
  const reg = /https?:\/\/([^\/]+)(\/[^?]*)/;
  const result = url.match(reg);
  
  if (result) {
    return {
      domain: result[1], // 第 1 組:域名
      path: result[2]    // 第 2 組:路徑
    };
  }
  return null;
}

const url = "https://www.baidu.com/s?wd=regex";
const parts = extractUrlParts(url);
console.log(parts);
// 運(yùn)行結(jié)果:
// { domain: "www.baidu.com", path: "/s" }

三、引用(\n 與 $n):復(fù)用分組捕獲結(jié)果

引用是基于分組的延伸特性,用于 “復(fù)用之前分組的捕獲結(jié)果”,分為 “正則內(nèi)引用”(\n)和 “代碼內(nèi)引用”($n 或 result[n]),能夠?qū)崿F(xiàn) “重復(fù)匹配”“動(dòng)態(tài)替換” 等高級(jí)功能。

1. 核心定義

  • 正則內(nèi)引用:用 \n(n 為分組序號(hào),從 1 開始)在正則表達(dá)式內(nèi)部引用第 n 個(gè)分組的捕獲結(jié)果;
  • 代碼內(nèi)引用:在代碼中(如 replace 方法)用 $n 引用第 n 個(gè)分組的結(jié)果,或通過 exec/match 的返回?cái)?shù)組 result[n] 獲取。

2. 語法規(guī)則

  • 分組序號(hào):從左到右數(shù)左括號(hào)的順序,第 1 個(gè)左括號(hào)為組 1,第 2 個(gè)為組 2,以此類推;
  • 非捕獲組:(?:pattern) 不捕獲結(jié)果,無法被引用;
  • 引用范圍:\n 僅在正則內(nèi)部生效,$n 僅在 replace 等字符串方法中生效,result[n] 適用于所有代碼場景。

3. 代碼案例與運(yùn)行結(jié)果

案例 1:正則內(nèi)引用(\n):匹配重復(fù)內(nèi)容

用 \1 引用第 1 組的結(jié)果,匹配 “前后重復(fù)的單詞”(如 hello hello):

javascript

運(yùn)行

// 分組1:匹配單詞(\w+),\1:引用分組1的結(jié)果,匹配重復(fù)單詞
const reg = /(\w+)\s+\1/;
const str1 = "hello hello";
const str2 = "hello world";
const str3 = "apple apple banana";

console.log(reg.test(str1)); // true(匹配 "hello hello")
console.log(reg.test(str2)); // false(無重復(fù)單詞)
console.log(str3.match(reg)); // ["apple apple", "apple"](匹配 "apple apple",分組1結(jié)果為 "apple")

案例 2:代碼內(nèi)引用($n):動(dòng)態(tài)替換內(nèi)容

在 replace 方法中用 $1、$2 引用分組結(jié)果,實(shí)現(xiàn) “格式化手機(jī)號(hào)”(中間 4 位打碼):

javascript

運(yùn)行

// 分組1:前 3 位數(shù)字,分組2:后 4 位數(shù)字
const phoneReg = /(\d{3})\d{4}(\d{4})/;
const phone = "13812345678";

// $1 引用分組1(138),$2 引用分組2(5678),中間用 **** 替換
const formattedPhone = phone.replace(phoneReg, "$1****$2");
console.log(formattedPhone); // 運(yùn)行結(jié)果:138****5678

案例 3:代碼內(nèi)引用(result [n]):提取分組詳情

通過 exec 或 match 的返回?cái)?shù)組獲取分組結(jié)果,提取 “身份證號(hào)中的出生日期”(第 7-14 位):

javascript

運(yùn)行

// 身份證號(hào)規(guī)則:18位,第 7-14 位為出生日期(yyyyMMdd)
const idCardReg = /^(\d{6})(\d{8})(\d{4})$/;
const idCard = "110101200001011234";

const result = idCardReg.exec(idCard);
if (result) {
  console.log("地區(qū)碼:", result[1]); // 地區(qū)碼:110101(第 1 組)
  console.log("出生日期:", result[2]); // 出生日期:20000101(第 2 組)
  console.log("校驗(yàn)碼:", result[3]); // 校驗(yàn)碼:1234(第 3 組)
}
// 運(yùn)行結(jié)果:
// 地區(qū)碼: 110101
// 出生日期: 20000101
// 校驗(yàn)碼: 1234

案例 4:引用的邊界場景(越界引用)

若引用的分組序號(hào)不存在(如引用第 3 組,但僅定義了 2 個(gè)分組),\n 會(huì)被視為普通字符:

javascript

運(yùn)行

// 僅定義 2 個(gè)分組,引用第 3 組(越界)
const reg = /(\d{2})-(\d{2})\3/;
const str1 = "05-203"; // 末尾為 "3",與 \3(視為普通字符 "3")匹配
const str2 = "05-204"; // 末尾為 "4",不匹配

console.log(reg.test(str1)); // true(\3 視為 "3",匹配 "05-203")
console.log(reg.test(str2)); // false(不匹配)

4. 實(shí)戰(zhàn)場景:修復(fù) HTML 標(biāo)簽(閉合不匹配的標(biāo)簽)

用引用修復(fù) “標(biāo)簽名不匹配” 的 HTML(如 <div>content</p>),將閉合標(biāo)簽改為與開始標(biāo)簽一致:

javascript

運(yùn)行

function fixHtmlTag(html) {
  // 分組1:匹配開始標(biāo)簽名(如 div),替換閉合標(biāo)簽為 $1(與開始標(biāo)簽一致)
  const reg = /<(\w+)>([\s\S]*?)<\/\w+>/;
  return html.replace(reg, "<$1>$2</$1>");
}

const wrongHtml = "<div>這是錯(cuò)誤的標(biāo)簽</p>";
const fixedHtml = fixHtmlTag(wrongHtml);
console.log(fixedHtml); // 運(yùn)行結(jié)果:<div>這是錯(cuò)誤的標(biāo)簽</div>

四、選擇、分組、引用的組合實(shí)戰(zhàn)

場景:驗(yàn)證并提取 “帶區(qū)號(hào)的固定電話”

固定電話規(guī)則:

  • 區(qū)號(hào):3-4 位數(shù)字,可選(如 010- 或 021-);
  • 號(hào)碼:7-8 位數(shù)字;
  • 分隔符:區(qū)號(hào)與號(hào)碼之間用 - 或 (空格)分隔;
  • 整體格式:[區(qū)號(hào)][分隔符][號(hào)碼](區(qū)號(hào)可選)。

實(shí)現(xiàn)代碼

javascript

運(yùn)行

function validateAndExtractLandline(phone) {
  // 分組1:區(qū)號(hào)(可選,3-4位數(shù)字),分組2:分隔符(- 或 空格),分組3:號(hào)碼(7-8位數(shù)字)
  const reg = /^(?:(\d{3,4})([- ]))?(\d{7,8})$/;
  const result = phone.match(reg);
  
  if (!result) {
    return "固定電話格式錯(cuò)誤";
  }
  
  return {
    fullPhone: result[0],
    areaCode: result[1] || "無區(qū)號(hào)", // 區(qū)號(hào)可選,無則返回 "無區(qū)號(hào)"
    number: result[3]
  };
}

// 測試案例
const phones = [
  "010-12345678",  // 帶區(qū)號(hào)(4位)+ "-" 分隔
  "021 87654321",  // 帶區(qū)號(hào)(3位)+ 空格分隔
  "1234567",       // 無區(qū)號(hào)(7位號(hào)碼)
  "010-1234567"    // 錯(cuò)誤(號(hào)碼僅 7 位,但區(qū)號(hào)+分隔符存在,需 8 位號(hào)碼)
];

phones.forEach(phone => {
  console.log(phone + ":", validateAndExtractLandline(phone));
});

運(yùn)行結(jié)果

plaintext

010-12345678: { fullPhone: '010-12345678', areaCode: '010', number: '12345678' }
021 87654321: { fullPhone: '021 87654321', areaCode: '021', number: '87654321' }
1234567: { fullPhone: '1234567', areaCode: '無區(qū)號(hào)', number: '1234567' }
010-1234567: 固定電話格式錯(cuò)誤

五、避坑指南

  • 選擇符的優(yōu)先級(jí)問題| 優(yōu)先級(jí)最低,若需限定選擇范圍,必須配合分組 (),否則會(huì)匹配 “左側(cè)全量 + 右側(cè)全量”(如 /a|bc/ 匹配 a 或 bc,而非 ab 或 ac);
  • 分組的捕獲與性能:無需引用分組結(jié)果時(shí),優(yōu)先用非捕獲組 (?:pattern),避免存儲(chǔ)無用的捕獲結(jié)果,提升正則匹配效率;
  • 引用的序號(hào)規(guī)則:分組序號(hào)按 “左括號(hào)出現(xiàn)順序” 計(jì)數(shù),嵌套分組需仔細(xì)數(shù)清序號(hào)(如 (a(b(c))) 中,組 1:a(b(c)),組 2:b(c),組 3:c);
  • 全局匹配的引用問題:用 g 修飾符時(shí),exec 會(huì)循環(huán)匹配,每次匹配的分組結(jié)果需通過 result[n] 實(shí)時(shí)獲取,不可復(fù)用之前的分組結(jié)果。

總結(jié)

選擇(|)、分組(())、引用(\n/$n)是正則表達(dá)式的 “三駕馬車”:

  • 選擇:實(shí)現(xiàn)多規(guī)則 “或” 邏輯,解決 “匹配多個(gè)候選模式” 的需求;
  • 分組:將多個(gè)字符打包成整體,支持批量控制和結(jié)果捕獲,是復(fù)雜規(guī)則的基礎(chǔ);
  • 引用:復(fù)用分組結(jié)果,實(shí)現(xiàn)重復(fù)匹配和動(dòng)態(tài)替換,提升正則的靈活性。

到此這篇關(guān)于JavaScript正則表達(dá)式之選擇、分組與引用的文章就介紹到這了,更多相關(guān)JS正則表達(dá)式選擇、分組與引用內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

最新評(píng)論

开封市| 安达市| 武穴市| 淳安县| 罗江县| 合水县| 威远县| 蒙阴县| 南郑县| 襄樊市| 台南县| 上饶市| 南江县| 施甸县| 襄汾县| 集安市| 郧西县| 隆子县| 乐东| 朔州市| 湖南省| 静海县| 栖霞市| 平南县| 九龙坡区| 霸州市| 大同县| 福贡县| 云南省| 班戈县| 宿迁市| 同江市| 轮台县| 融水| 扎赉特旗| 荔浦县| 衢州市| 鄂托克旗| 新龙县| 淮南市| 达州市|