Bash 4.4下多行正则捕获HTML标签与transloco键值分组问题
问题原因
- 原方案使用
grep -Pzo仅能输出完整匹配串,无法直接提取命名捕获组的内容、偏移量信息,你通过read按行拆分匹配结果的逻辑,会把跨多行的匹配串拆成多个独立项,导致输出混乱 - 原正则存在边界匹配漏洞:标签名匹配未做限制,会将标签属性、后续标签内容误匹配到
tag分组,非贪婪逻辑失效导致跨标签匹配
解决方案
推荐使用Perl实现需求,Perl默认内置完善的PCRE正则支持,可直接读取命名捕获组、偏移量信息,无需额外安装依赖,适配你使用的Bash 4.4环境。
调整后的完整可运行代码如下:
text=" <div> <span> {{ 'setup.steps.accountInfo' | transloco }} </span> <span> {{ 'setup.steps.accountInfo' | transloco }} </span> <button mat-icon-button class=\"setup__back-btn\" [ngClass]=\"{ 'setup__back-btn--visible': activePane === 'right' }\" (click)=\"onPaneToggleClicked('left')\"> {{ 'setup.steps.accountInfo' | transloco }} </button> " echo "$text" | perl -e ' use strict; use warnings; my $content = do { local $/; <STDIN> }; # 正则修饰符s:让.匹配换行;x:允许正则内加注释空格 my $pattern = qr{ <(?<tag>[a-zA-Z][a-zA-Z0-9-_]*) # 匹配合法HTML标签名,存入tag分组 [^>]*> # 跳过标签所有属性直到闭合尖括号 .*? # 非贪婪匹配标签内内容,避免跨标签 {{ # 匹配插值语法开头 \s*[\'\"]? # 可选的引号、前置空格 (?<name>[^\'\"]*?) # 匹配transloco键名,存入name分组 [\'\"]?\s*\|\s*transloco\s*}} # 匹配后续transloco语法 .*?</\g{tag}> # 匹配到对应闭合标签 }sx; my $match_count = 0; # 全局遍历所有匹配 while ($content =~ /$pattern/g) { $match_count++; my $tag = $+{tag}; my $name = $+{name}; # 计算分组偏移($-[n]为分组起始偏移,$+[n]为分组结束偏移) my $tag_start = $-[1] + 1; my $tag_end = $+[1]; my $name_start = $-[2] + 1; my $name_end = $+[2]; # 按要求格式输出 print "match $match_count\n"; printf "group tag %d-%d %s\n", $tag_start, $tag_end, $tag; printf "group name %d-%d %s\n\n", $name_start, $name_end, $name; } '
运行上述代码会输出完全符合你要求的格式,除了两个span标签的匹配结果外,也会正确匹配到包含transloco语法的button标签。如果需要添加行号输出,可以在Perl代码中预处理每行的起始偏移,根据捕获组的偏移查询对应行号即可。
内容的提问来源于stack exchange,提问作者Qhori
相关产品推荐
相关产品推荐

