Perl中含正则表达式的哈希反转及qr对象转文本实现
Perl 反转LaTeX转HTML哈希实现HTML转LaTeX
核心问题解决思路
要反转以qr//正则对象为键的哈希,关键是从qr对象中提取原始正则模式和修饰符,再自动构造反转后的匹配规则与替换字符串。
步骤1:提取qr对象的正则模式与修饰符
Perl中qr//对象字符串化后会呈现(?^:pattern)或(?^i:pattern)格式,通过正则解析可以提取出原始模式和修饰符:
sub extract_qr { my ($qr) = @_; my $str = "$qr"; die "无效的qr对象格式: $str" unless $str =~ /^\(\?([^:]*):(.*)\)$/; my ($mods, $pattern) = ($1, $2); $mods =~ s/^//; # 移除Perl默认的^标记 return ($pattern, $mods); }
步骤2:计数原正则的捕获组数量
为了对应反转后的捕获组引用,需要统计原正则中捕获组(排除非捕获组(?:...))的数量:
sub count_captures { my ($pattern) = @_; my $count = 0; # 匹配所有非非捕获组的左括号 while ($pattern =~ /\((?!\?:)/g) { $count++; } return $count; }
步骤3:转义HTML字符串中的正则特殊字符
构造反转后的匹配正则时,需要转义HTML中的正则特殊字符(如<、>、/等):
sub escape_regex { my ($str) = @_; $str =~ s/([\.\+\*\?\[\]\^\$\(\)\{\}\|\-\\])/\\$1/g; return $str; }
步骤4:自动生成反转哈希
遍历原哈希,为每个键值对生成反转后的正则与替换字符串:
# 示例原哈希:LaTeX正则 → HTML字符串 my %replace = ( qr/\\bold{(.*?)}/ => '<strong>$1</strong>', qr/\\italic{(.*?)}/ => '<em>$1</em>', qr/\\underline{(.*?)}/ => '<u>$1</u>', ); my %reverse_replace; foreach my $latex_re (keys %replace) { my $html_str = $replace{$latex_re}; my ($latex_pat, $mods) = extract_qr($latex_re); my $num_captures = count_captures($latex_pat); # 构造反转后的匹配正则(匹配HTML) my $temp_html = $html_str; # 先将$1/$2等标记替换为占位符,避免转义干扰 $temp_html =~ s/\$(\d+)/__CAP__$1__/g; # 转义正则特殊字符 $temp_html = escape_regex($temp_html); # 替换占位符为捕获组 $temp_html =~ s/__CAP__(\d+)__/(.*?)/g; # 编译反转后的正则对象 my $reverse_re = eval "qr/$temp_html/$mods"; die "反转正则编译失败: $@" if $@; # 构造反转后的替换字符串(LaTeX格式) my $reverse_replace_str = $latex_pat; my $cap_num = 1; # 将原正则的捕获组替换为$1/$2等引用 $reverse_replace_str =~ s/\((?!\?:)/\$$cap_num++/ge; # 存入反转哈希(注意:若存在多对一映射需处理冲突) $reverse_replace{$reverse_re} = $reverse_replace_str; }
测试反转功能
my $html_text = '<strong>Hello</strong> <em>World</em>'; foreach my $re (keys %reverse_replace) { $html_text =~ s/$re/$reverse_replace{$re}/g; } print $html_text; # 输出:\bold{Hello} \italic{World}
注意事项
- 若原正则包含嵌套捕获组,
count_captures会正确计数所有层级的捕获组; - 若原替换值包含
$0(整个匹配内容),需额外添加处理逻辑; - 若存在多个LaTeX正则对应同一HTML字符串,需手动处理哈希键冲突问题。
内容的提问来源于stack exchange,提问作者Henri_S
相关产品推荐
相关产品推荐

