马黑黑 发表于 2024-3-3 19:32

正则表达式在JS中的构建及实现文本匹配替换

本帖最后由 马黑黑 于 2024-3-3 19:36 编辑 <br /><br /><style>
.ma { font-size: 18px; }
.ma p, .ma pre { margin: 10px 0; }
.ma pre { font-size: 16px; }
.ma mark { padding: 0 6px; background: lightblue; }

.mum { position: relative; margin: 0; padding: 10px; font: normal 16px/20px Consolas, Monaco, 'Andale Mono', 'Ubuntu Mono', monospace; color: black; background: rgba(240, 240, 240,.95); border: thin dashed gray; border-radius: 6px; }
.mum ::selection { background-color: rgba(0,100,100,.35); }
.mum div { margin: 0; padding: 0; }
.mum cl-cd { display: block; position: relative; margin: 0 0 0 50px; padding: 0 0 0 10px; white-space: pre-wrap; overflow-wrap: break-word; border-left: 1px solid silver; }
.mum cl-cd::before { position: absolute; content: attr(data-idx); width: 50px; color: gray; text-align: right; transform: translate(-70px); }
.tRed { color: red; }
.tBlue { color: blue; }
.tGreen { color: green; }
.tDarkRed { color: darkred; }
.tMagenta { color: magenta; }
</style>

<div class="ma">

<h2>正则表达式在JS中的构建与文本匹配替换</h2>
<p>正则表达式,英文名称为 Regular Expression,regular意为规则,express是表达式。正则表达式用于文本查找,是对查找关键词的规则描述。我们查找特定的文本内容,总是要通过关键词进行查找,关键词可以是精准的,也可以是模糊的,比方说,我们要在名册中查找“王大军”,这可以用精准查找,“王大军”就是查找关键词,查找的对象也是“王大军”;而当我们想查找的是不论姓什么,名叫“大军”的都找出来,这时候的查找就需要设定一个关键词描述,令其可以模糊匹配名册中的姓名中有“大军”的所有姓名。不论精准匹配,还是模糊匹配,正则表达式都能胜任。</p>
<p>下面有一份名册片段,我们要查找出所有姓名中有“大军”二字的姓名:</p>
<pre id="namelist">欧阳军何晓阳方丽丽范大军黄杨大军唐小红大军饶树龙韩小军聂大军龙家俊</pre>
<p><button id="sFind" type="button" value="0" onclick="findNames(namelist,'大军')">查找含有大军的所有姓名</button></p>
<p>点击上方按钮,见证奇迹。咋这么神奇呢?这就是正则表达式的功劳。这里,我们构建了一个查找关键词:</p>

<div class='mum'>
<cl-cd data-idx="1">/[一-龥]*大军/g</cl-cd>
</div>

<p>符号<mark>//</mark>用以包裹正则表达式:<mark>[一-龥]*</mark>中,中括号里的内容是汉字<mark>一</mark>到汉字<mark>龥</mark>的所有汉字,<mark>*</mark>表示这些汉字出现0次或多次;<mark>大军</mark>是字面量,容易理解,不多解释。<mark>g</mark>是正则表达式的一个开关,表示全局查找,这根据需要而定,查找全部的符合规则的目标字串,需要它。</p>
<p>正则表达式要用在编程语言中,JavaScript(简称JS)就是一门编程语言。在JS里,我们有两种方式声明和构建正则表达式:</p>

<div class='mum'>
<cl-cd data-idx="1"><span class="tGreen">//方法一:</span></cl-cd>
<cl-cd data-idx="2"><span class="tBlue">let</span> reg1 = /[一-龥]*大军/g;</cl-cd>
<cl-cd data-idx="3">&nbsp;</cl-cd>
<cl-cd data-idx="4"><span class="tGreen">//方法二:</span></cl-cd>
<cl-cd data-idx="5"><span class="tBlue">let</span> reg2 = <span class="tBlue">new</span> <span class="tRed">RegExp</span>(<span class="tMagenta">'[一-龥]*大军'</span>, <span class="tMagenta">'g'</span>);</cl-cd>
</div>

<p>这两种方法表达的都是全局匹配含有“大军”的中文姓名。方法一更简洁,方法二则在构造含有JS变量的正则表达式时更具灵活性,可以拼接字面量和变量。</p>
<p>那如何给符合查找特征的名字标红呢?看看本文的函数:</p>

<div class='mum'>
<cl-cd data-idx="1"><span class="tBlue">function</span> findNames(ele,keyword) {</cl-cd>
<cl-cd data-idx="2">&nbsp; &nbsp; <span class="tBlue">var</span> str = ele.innerText;</cl-cd>
<cl-cd data-idx="3">&nbsp; &nbsp; <span class="tBlue">var</span> reg = <span class="tBlue">new</span> <span class="tRed">RegExp</span>(<span class="tMagenta">'([一-龥]*'</span> + keyword + <span class="tMagenta">')'</span>, <span class="tMagenta">'g'</span>);</cl-cd>
<cl-cd data-idx="4">&nbsp; &nbsp; ele.innerHTML = str.replace(reg, <span class="tMagenta">'&lt;<span class="tDarkRed">span</span> class="tRed"&gt;$1&lt;/<span class="tDarkRed">span</span>&gt;'</span>);</cl-cd>
<cl-cd data-idx="5">};</cl-cd>
</div>

<p>findNames 这个函数需要两个参数,ele 是文本容器变量,keyword 是查找关键字变量。函数里,我们先声明一个变量 str 令其等于文本容器的文本内容(innerText),接着构建一个正则表达式并赋值给变量 reg,然后用JS内置的 replace 函数(也可以使用replaceAll函数)替换 str 文本:将符合正则表达式描述规则的文本通通替换为带 span 标签的字串,这个 span 标签有一个class属性,通过事先设置好的CSS设定给匹配正则表达式的文本着色,着色后的 str 文本再装回文本容器(innerHTML)。点击前面的按钮,就是调用的这个函数。</p>

</div>

<script>
function findNames(ele,keyword) {
        var str = ele.innerText;
        var reg = new RegExp('([一-龥]*' + keyword + ')', 'g');
        ele.innerHTML = str.replace(reg, '<span class="tRed">$1</span>');
};
</script>

红影 发表于 2024-3-3 20:51

查找挺好理解,记住两个正则表达式九可以了。替换还挺麻烦的,要先设置好CSS,不能直接给颜色么?

马黑黑 发表于 2024-3-3 20:56

红影 发表于 2024-3-3 20:51
查找挺好理解,记住两个正则表达式九可以了。替换还挺麻烦的,要先设置好CSS,不能直接给颜色么?
颜色渲染是要使用CSS的。你若不想用独立的CSS,那么,可以用行内style:

<span style="color: red;">姓名</span>

一般来说,能不用行内CSS就尽量不适用,这是规范要求,而这个要求是有理由的:行内style属性日后不好批量维护。

红影 发表于 2024-3-3 21:00

JS那个reg =式子里的' + keyword + '就代替了大军两字吧,因为加了这个,又多了个小括号?

马黑黑 发表于 2024-3-3 21:06

本帖最后由 马黑黑 于 2024-3-3 21:07 编辑

红影 发表于 2024-3-3 21:00
JS那个reg =式子里的' + keyword + '就代替了大军两字吧,因为加了这个,又多了个小括号?
这个用了字串拼接,同时也是后面替换的需求。

要替换正则表达式且保留匹配部分的文字,就需要分组,正则表达式中的分组用小括号包裹:

str = str.replace(/(正则表达式)/g, '...$1...');

上面,正则表达式的红色部分,小括号是分组用,替换成的部分中,$1指向它。分多少个组,替换成都用 $n 表示,n 从 1 开始。

南无月 发表于 2024-3-3 21:49

试试找个王大军{:4_170:}韩小军没被飘红。
这个正则表达找法很精准啊,能找到还能飘红。。黑老师厉害。

南无月 发表于 2024-3-3 21:50

对查找关键词要规则描述。。。这个音画编辑器里的查找也是这个原理吧。

马黑黑 发表于 2024-3-3 21:51

南无月 发表于 2024-3-3 21:50
对查找关键词要规则描述。。。这个音画编辑器里的查找也是这个原理吧。

那个不是,那个是精准查找

红影 发表于 2024-3-3 22:13

马黑黑 发表于 2024-3-3 20:56
颜色渲染是要使用CSS的。你若不想用独立的CSS,那么,可以用行内style:

姓名


我们这都是玩,很少有批量维护的时候啊,所以行内的最省力了{:4_173:}

马黑黑 发表于 2024-3-3 22:14

红影 发表于 2024-3-3 22:13
我们这都是玩,很少有批量维护的时候啊,所以行内的最省力了

那不见得省力。行内是迫不得已才回去使用的。

红影 发表于 2024-3-3 22:15

马黑黑 发表于 2024-3-3 21:06
这个用了字串拼接,同时也是后面替换的需求。

要替换正则表达式且保留匹配部分的文字,就需要分组,正 ...

这个解说非常清晰,谢谢黑黑{:4_187:}

马黑黑 发表于 2024-3-3 22:16

红影 发表于 2024-3-3 22:15
这个解说非常清晰,谢谢黑黑

{:4_190:}

红影 发表于 2024-3-3 22:42

马黑黑 发表于 2024-3-3 22:14
那不见得省力。行内是迫不得已才回去使用的。

嗯嗯,不应该养成这样的习惯。

红影 发表于 2024-3-3 22:42

马黑黑 发表于 2024-3-3 22:16


本来看得糊里糊涂的,被你一说,明白了{:4_187:}

马黑黑 发表于 2024-3-3 23:25

红影 发表于 2024-3-3 22:42
本来看得糊里糊涂的,被你一说,明白了

{:4_190:}

马黑黑 发表于 2024-3-3 23:27

红影 发表于 2024-3-3 22:42
嗯嗯,不应该养成这样的习惯。

一般不建议。使用时,浏览器严格模式下也会建议你改的

红影 发表于 2024-3-4 09:54

马黑黑 发表于 2024-3-3 23:25


我对JS真的太不熟了的缘故{:4_173:}

红影 发表于 2024-3-4 09:55

马黑黑 发表于 2024-3-3 23:27
一般不建议。使用时,浏览器严格模式下也会建议你改的

还好我们这里没建议过{:4_173:}

马黑黑 发表于 2024-3-4 11:38

红影 发表于 2024-3-4 09:55
还好我们这里没建议过

大方向要求如此,不过也不是不能用

马黑黑 发表于 2024-3-4 11:38

红影 发表于 2024-3-4 09:54
我对JS真的太不熟了的缘故

JS没啥,数学好就行
页: [1] 2 3 4 5
查看完整版本: 正则表达式在JS中的构建及实现文本匹配替换