代码之家  ›  专栏  ›  技术社区  ›  sid_com

如何动态创建替换?

  •  2
  • sid_com  · 技术社区  · 6 年前

    如何向替换动态添加修改器?

    my $str = 'aaBaabaabaa';
    my $mod = 'g';
    $str =~ s/b// + $mod;
    
    1 回复  |  直到 6 年前
        1
  •  2
  •   Stefan Becker    6 年前

    qr/(?X:).../ 不适用于仅限操作的修改器,如 /g

    一种可能的办法是:

    #!/usr/bin/perl
    use strict;
    use warnings;
    
    my $str = 'aaBaabaabaa';
    
    print "BEFORE: ${str}\n";
    
    # regex configuration
    my $pattern     = '(.)(.)'; # 'b';
    my $replacement = '"$2$1"'; # '';
    my $mod         = 'ieg';    # 'g';
    
    # extract operation-only modifiers
    my $operation_only = qr/([ge])/;
    my %special;
    $special{$_}++ foreach ($mod =~ /$operation_only/g);
    my $mod_filtered;
    ($mod_filtered = $mod) =~ s/$operation_only//g;
    
    # generate regex
    my $regex    = "(?${mod_filtered}:${pattern})";
    my $compiled = qr/$regex/;
    print "s/ ${regex} -> ${compiled} / ${replacement} / $mod -> ", join('', sort keys %special), "\n";
    
    # execute substitution
    my $replacement_code = sub { return $replacement };
    for (1..$special{e} // 0) {
        my $recurse = $replacement_code;
        $replacement_code = sub { return eval $recurse->() };
    }
    
    if (exists $special{g}) {
        $str =~ s/$compiled/$replacement_code->()/ge;
    } else {
        $str =~ s/$compiled/$replacement_code->()/e;
    }
    
    print "AFTER:  ${str}\n";
    
    exit 0;
    

    $ perl dummy.pl
    BEFORE: aaBaabaabaa
    s/ (?i:(.)(.)) -> (?^:(?i:(.)(.))) / "$2$1" / ieg -> eg
    AFTER:  aaaBbaaaaba