已掉线,重新登录

首页 > 绿虎论坛 > 历史版块 > 编程 > 其他编程语言 > 讨论/求助

标题: 正则求助:找出非闭合的img标签

作者: @Ta

时间: 2022-02-10发布,2022-02-10修改

点击: 17105

测试文本


<img 
v-if="test>a" 
src="url">
<text>文本</text>

如何找出上文中未闭合的img标签呢:

<img 
v-if="test>a" 
src="url">

其实就是如何排除带 <> 的属性干扰

手动@老虎会游泳
小米MIX2s(白)


[隐藏样式|查看源码]


『回复列表(37|隐藏机器人聊天)』

1.

@水木易安

/<img\b\s*([^\s<='"\/>]+(=([^"'<\/>]+|"[^"]*"|'[^']*'))?\s*)*>/

可以匹配以下内容:

<img>
<img checked>
<img selected x-aaa="b>c/d" data-bbb='e<f/g' height=500.25>

不匹配以下内容:

<img/>
<img checked />

匹配以下内容时遇到回溯灾难(匹配永不结束),需要优化:

<img selected x-aaa="b>c/d" data-bbb='e<f/g' height=500.25 />

关于回溯灾难:https://hu60.cn/q.php/bbs.topic.89212.html

使用 https://regex101.com/ 进行正则表达式调试。注意:只有PCRE可以使用调试器,如果选了JS,调试器选项会消失。

(/@Ta/2022-02-10 05:56//)

2.
/<img\b\s*([A-Za-z_][A-Za-z0-9-_]*(=(-?[0-9]+(\.[0-9]+)?([Ee][+-]?[0-9]+)?|'[^']*'|"[^"]*"))?\s*)*>/

写成这样在js里能够不匹配,但依然用时很久。在PHP里还是灾难性回溯。

image.png

(/@Ta/2022-02-10 05:16//)

3.

把规则放简单一点,忽略height=500.25这种不加引号的写法,和selected这种没有值的写法,就不会灾难性回溯了:

/<img\s*([A-Za-z_][A-Za-z0-9-_]*=('[^']*'|"[^"]*")\s*)+>/

image.png

image.png

(/@Ta/2022-02-10 05:28//)

4.

至于“如何排除带 <> 的属性干扰”,答案倒是很简单:

('[^']*'|"[^"]*")
(/@Ta/2022-02-10 05:25//)

5.

看起来这种写法的开销很大,这个?是性能杀手。

(=('[^']*'|"[^"]*"))?

这个表达式在灾难性回溯的边缘,内容稍微多一点就要匹配很久:

/<img\s*([A-Za-z_][A-Za-z0-9-_]*(=('[^']*'|"[^"]*"))?\s*)+>/

image.png

image.png

匹配尝试了11万步:

image.png

(/@Ta/2022-02-10 05:44//)

6.

总算找到灾难性回溯的根源了。
其实结尾的\s*才是性能杀手。\s*表示:属性之间可以有空格,也可以没有空格。
而“属性之间没有空格”这种选择,才是导致一系列回溯的原因,因为正则表达式引擎在试图把单个属性拆分成各个不同的部分(比如selected可以切分成selected,还可以切分成selected,等等)。

改成\s+并且放在属性的前面,就不会有这种问题了。

/<img(\s+[A-Za-z_][A-Za-z0-9-_]*(=(-?[0-9]+(\.[0-9]+)?([Ee][+-]?[0-9]+)?|'[^']*'|"[^"]*"))?)*\s*>/

现在最难的不匹配只需300步:

image.png

(/@Ta/2022-02-10 05:51//)

7.

1楼的否定集合表示法也可以这样改造:

/<img(\s+[^\s<='"\/>]+(=([^"'<\/>]+|"[^"]*"|'[^']*'))?)*\s*>/

匹配48步:

image.png

不匹配300步:

image.png

性能相当优秀。

(/@Ta/2022-02-10 05:57//)

8.

上面的表达式依然不完备,比如这就无法匹配到,而它是合法的HTML代码:

image.png

HTML代码

浏览器解析后:

图片.png

(/@Ta/2022-02-10 07:03//)

9.

看起来,正则表达式很难完美的完成匹配,至少手写的不太行。总会有各种各样未能匹配到的特例。

就连完美的匹配这个字符串都很难:

"abc\"def\\" + "\\ghi\njkl"

不过如果只是匹配非常标准的HTML写法,没有不打空格不打引号等特例,那('[^']*'|"[^"]*")应该就足够了。

(/@Ta/2022-02-10 07:19//)

10.

举一个错误匹配的绝佳例子:

<div data-test='<img src="xxx.jpg">'></div>

在不进行全面语法分析的情况下,没有任何办法避免错误匹配到这个<img src="xxx.jpg">

(/@Ta/2022-02-10 07:27//)

11.

好家伙,
不愧是老虎,
当我琢磨了半天的正则无果之后,
扔了一个求助帖就睡了,
然后第二天被长篇大论的回复震惊到让我联想到这个视频

视频链接

非常感谢,我先琢磨一下回复。

小米MIX2s(白)

(/@Ta/2022-02-10 10:14//)

12.

@老虎会游泳,请问一下#6 楼中的 RegEx Debugger 是什么来的呀
小米MIX2s(白)

(/@Ta/2022-02-10 14:23//)

13.

找到了 登录账号以后就能用了
小米MIX2s(白)

(/@Ta/2022-02-10 14:39//)

14.

@水木易安,不需要登录,只是只有PCRE可以使用调试器,如果选了JS,调试器选项会消失。此外,还要先输入一个表达式才能点调试器。

(/@Ta/2022-02-10 15:43//)

15.

@老虎会游泳,原来如此
小米MIX2s(白)

(/@Ta/2022-02-10 17:33//)

16.

除了@老虎会游泳 提到的regex101.com,再安利一个exe的正则神器regexbuddy

坏孩子,其实你很好,但是还不够好

(/@Ta/2022-02-10 20:05//)

17.

regex101.com好像还有人给做了个中文版的: 嗨正则https://hiregex.com(这个好像还不是反代 ?)
坏孩子,其实你很好,但是还不够好

(/@Ta/2022-02-10 20:07//)

18.

@老虎会游泳,新的问题

第一个是箭头函数,好像误判了

/<img(\s+[^\s<='"\/>]+(=([^"'<\/>]+|"[^"]*"|'[^']*'))?)*\s*>(.*<\/img>)?/gmi

case:



		<img onclick={()=>alert({msg:123})} src="../../image/home/right_icon.png" style="height:9px" />


		<img>
		<img checked>

		<img />

		<img v-if="a>b"></img>

小米MIX2s(白)

(/@Ta/2022-03-08 12:00//)

19.
(/@Ta/2022-03-08 14:14//)

下一页 1/2页,共37楼

回复需要登录

7月2日 14:18 星期三

本站由hu60wap6驱动

备案号: 京ICP备18041936号-1