You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.11 19:53:15