马黑黑 发表于 2023-1-13 13:09

正则:匹配代码注释

web文档存在三种类型的代码:CSS、HTML和JavaScript。这三中代码,它们都拥有自己的注释规则:

一、CSS 用 /* 注释文本 */

头尾是边界符号,分别 /* 和*/,它们之间则是注释的文本。边界符号之内的注释文本可以是多行,以下是 CSS 代码注释举例:

/*index.html 专用
    创建 : 2022年11月10日
    修改 : 2023年1月12日
*/
html, body
    margin: 0; /* 外边距 */
    padding: 0; /* 内边距 */
    width: 100%; /* 宽度 */
    height: 100%; /* 外边距 */
}

二、HTML 用 <!-- 注释文本 -->

原理同CSS,起始边界字符分别为 <!-- 和 --> 。注释文本同样支持单行和多行。

三、JS用 //注释文本 和 /* 注释文本 */ 共两种方式


其中,//注释文本 专用与单行注释,/* 注释文本 */ 可用于单行和多行注释(情形同CSS)。

小结:HTML文档可能出现的三种注释形式——

① /* 注释文本 */ 【单行+多行】
② <!-- 注释文本 --> 【单行+多行】
③ //注释文本 【单行】


现在来看看如何使用正则表达式去匹配这些注释。

先匹配最简单的 “//注释”,它的关键在于两个斜杠“//”,这是它的构造特点,然后后面是任意的文本(包含空格)。如此,可以这样构造匹配这类注释的正则表达式:

\/\/.*

啥?看官不要晕,我来一一解释。

上面的式子,看到斜杠了吧?我给他们标红的那两个字符。为什么它们的前面要用反斜杠 \ 呢?因为斜杠 \ 是js的注释用字符,所以需要用反斜杠了进行转义,如果不转义,JS在运行的时候容易出现问题。所以,\/\/ 其实就是 \\ 。

.* 又是啥?在正则里,. 是换行符以外的任意字符,* 是个量词,表示前面的点号 . 所代表的字符出现0或多次。

那么,整个式子意思就是:一个文本串,出现 // 这个符号,且其后面是任意N个(N≥0)换行符以外的字符。

那么,如果以上式子所描述的规则能在目标文本群中找到合适的句子,就叫匹配。

再来看如何匹配 <!-- 注释文本 --> ,我这么写式子 :

<!--[^(-->)]*-->


这个式子按颜色分为三部分:红色的 <!-- 容易懂,就是HTML注释的起头部分,红紫色的 --> 也容易懂,是注释的结尾部分,中间蓝色的 [^(-->)]* 要专门解释一下——

使用中括号 [] 是为了使用否定符号 ^ 。在正则里,有否定一个字符,可以用 [^我] 的形式表示对字符“我”的否定,[^我]的意思是在这个位置不能出现“我”这个字符。回到上面构造的式子,^ 否定的是小括号里的整体字符 --> ,--> 是一个整体,所以表达位(-->) 。

那么,整个式子 <!--[^(-->)]*--> 的意思是,字符串以 <!-- 起头,随后不能有 --> 出现,最后是 --> 收尾。

以上式子,是按照HTML注释规范去构造,它可以匹配单行和多行注释,因为呢,中间部分只排除了 --> 字符,换行符就会包含在了里面。

最后匹配/* 注释文本 */ ,这个麻烦一点,以我的功力,需要分开单行和多行处理:

匹配单行:\/\*.*\*\/


头尾分别描述 /* 和 */,符号 / 和 * 都需要转义(\)。中间是.* ,前面解释过的,换行符以外的任意字符出现0此或任意多次。这个能适配单行,但不能匹配多行。

匹配多行:\/\*[^(\*\/)]*\*\/


这个,原理和HTML注释是一样的,有否定法排除收尾符号在中间出现,从而达到匹配多行的目的。

把这两个式子用符号 | 合并起来,就能匹配单行和单行了:


(\/\*.*\*\/)|(\/\*[^(\*\/)]*\*\/)


红紫色的括号是新加上去的,目的是让分组明晰,维护是容易找到。

嗯,在JS里,声明一个正则表达式的语句可以是这样:

    let re = /正则表达式/g;

其中,g 是一个全局开关,有它没它很不同,这里先不说。把我们刚分析完的匹配 /*注释*/ 的式子写进去,就变成酱紫:

    let re = /(\/\*.*\*\/)|(\/\*[^(\*\/)]*\*\/)/g;

如果三种类型的注释都有匹配,声明写成酱紫(我不着色了):

    let re = /(\/\/.*)|(<!--[^(-->)]*-->)|(\/\*[^(\*\/)]*\*\/)|(\/\*.*\*\/)/g;

正则很烧脑,也很神奇。不妨看看楼下的例子,双击一下文本框。

马黑黑 发表于 2023-1-13 13:10

<textarea id="mydiv" rows="20" cols="60">
        //注释1
        代码1
        // 注释2
        代码2
        /* 注释3 */
        代码3 /**ok **/
          /* 注释4 多行注释
                        这里也是注释内容 来删我啊
        */
        代码4 // 注释4
        <!-- HTML注释1 -->
        HTML代码1
        <!-- HTML注释2
                这里也是注释内容 来删我呀
        -->
        HTML代码2
</textarea>

<script>

let delExegesis = () => {
        let str = mydiv.value;
        let re = /(\/\/.*)|(<!--[^(-->)]*-->)|(\/\*[^(\*\/)]*\*\/)|(\/\*.*\*\/)/g;
        str = str.replace(re, '');
        mydiv.value = str;
};

mydiv.ondblclick = () => delExegesis();

</script>

马黑黑 发表于 2023-1-13 13:30

二楼演示,也可以将其它任何有注释的代码或文本粘贴到文本框,然后双击文本框查看过滤效果

红影 发表于 2023-1-13 15:04

哈,看官已经晕了。注释的.*还没整明呢,再加上用反斜杠的转义,样式上首先就看晕了。{:4_173:}

红影 发表于 2023-1-13 15:18

匹配单行:\/\*.*\*\/   ——这个拿掉头尾,还剩.*

匹配多行:\/\*[^(\*\/)]*\*\/ ——这个拿掉头尾不知道剩什么了,貌似小括号里的也转义了,也就是注释的结尾部分先出现一遍?

红影 发表于 2023-1-13 15:32

好像有点点看明白了,//注释文本的那个式子表达的是,不包含换行符的任意字符的文本串
                              <!-- 注释文本 -->表达的是,只要不带结尾符 --> 的全算数
                           /* 注释文本 */ 比较麻烦,有转义捣乱,还分单行多行,但意思和第一个一样,就是不包含换行符的任意字符

红影 发表于 2023-1-13 15:34

这个太难看得明白了,还好黑黑细心地标上了颜色,跟着颜色抽丝剥茧,倒是慢慢可以有点感觉了。黑黑辛苦了{:4_190:}

马黑黑 发表于 2023-1-13 20:58

红影 发表于 2023-1-13 15:34
这个太难看得明白了,还好黑黑细心地标上了颜色,跟着颜色抽丝剥茧,倒是慢慢可以有点感觉了。黑黑辛苦了{: ...

不过我做的不是很完美,尤其是 /**/ 的多行正则,总感觉哪里不对劲儿,有空再想想。

马黑黑 发表于 2023-1-13 21:01

红影 发表于 2023-1-13 15:04
哈,看官已经晕了。注释的.*还没整明呢,再加上用反斜杠的转义,样式上首先就看晕了。

.* 实际上也是一个组合,和我们平时在电脑里查找文件用的通配符差不多的,表示任意字符(换行符除外)出现0次或多次。

马黑黑 发表于 2023-1-13 21:02

红影 发表于 2023-1-13 15:18
匹配单行:\/\*.*\*\/   ——这个拿掉头尾,还剩.*

匹配多行:\/\*[^(\*\/)]*\*\/ ——这个拿掉头尾不知 ...

小括号里的内容,去掉转义符,就是 */

马黑黑 发表于 2023-1-13 21:04

红影 发表于 2023-1-13 15:32
好像有点点看明白了,//注释文本的那个式子表达的是,不包含换行符的任意字符的文本串
                   ...

反正感觉很绕是吧?正则就是如此,自己写的隔几天再看也会出现看不懂的情形{:4_170:}

红影 发表于 2023-1-13 23:06

马黑黑 发表于 2023-1-13 20:58
不过我做的不是很完美,尤其是 /**/ 的多行正则,总感觉哪里不对劲儿,有空再想想。

本来对这个一点都不懂,看了黑黑的帖子,有点明白了。

红影 发表于 2023-1-13 23:06

马黑黑 发表于 2023-1-13 21:01
.* 实际上也是一个组合,和我们平时在电脑里查找文件用的通配符差不多的,表示任意字符(换行符除外)出 ...

嗯嗯,现在知道了。

红影 发表于 2023-1-13 23:10

马黑黑 发表于 2023-1-13 21:02
小括号里的内容,去掉转义符,就是 */

\/\*[^(\*\/)]*\*\/ 这个还是有点不太明白,带转义符的去掉了后,小括号里好像没东西了,只剩中括号外面的一个*?

红影 发表于 2023-1-13 23:11

马黑黑 发表于 2023-1-13 21:04
反正感觉很绕是吧?正则就是如此,自己写的隔几天再看也会出现看不懂的情形

是的,尤其本来就对它们不熟{:4_173:}

马黑黑 发表于 2023-1-13 23:14

红影 发表于 2023-1-13 23:11
是的,尤其本来就对它们不熟

即使熟悉,也会弄混

马黑黑 发表于 2023-1-13 23:15

红影 发表于 2023-1-13 23:10
\/\*[^(\*\/)]*\*\/ 这个还是有点不太明白,带转义符的去掉了后,小括号里好像没东西了,只剩中括号外面 ...

这个说过的吧。(\*\/)里面,是 */ ,我设计这个是用排除法,中间不是 */ 就匹配的意思

马黑黑 发表于 2023-1-13 23:17

红影 发表于 2023-1-13 23:06
本来对这个一点都不懂,看了黑黑的帖子,有点明白了。

正则表达式多少懂点是好的。它设计之初就是用来表达极难描述的神经研究方面的东东,后来用到编程领域,非常强大

红影 发表于 2023-1-13 23:21

马黑黑 发表于 2023-1-13 23:14
即使熟悉,也会弄混

这个帖子我得多看看,省得下次再见到这类表达总是云里雾里的{:4_173:}

红影 发表于 2023-1-13 23:26

马黑黑 发表于 2023-1-13 23:15
这个说过的吧。(\*\/)里面,是 */ ,我设计这个是用排除法,中间不是 */ 就匹配的意思

我被这里面的2个转义符弄迷糊了。
页: [1] 2 3 4
查看完整版本: 正则:匹配代码注释