Perl相当于“vi”编辑器中的`&`占位符

时间:2018-03-07 00:19:26

标签: regex perl

使用 vi 屏幕编辑器,我会这样做

%s/^drop table .*/exec rename_table('&')/g

允许我重新格式化找到的字符串。我需要在Perl中做同样的事情。

我编写了一个模块,我将模式传递给$regexp和替换$newtxt字符串。

此模块

if ( $_ !~ /$regexp/ ) {
    print FOUT;
}
else {
    s/$regexp/$newtxt/g;
    print FOUT;
}

我试过

perl_swap( '(drop table .*);' , 'echo $3;' )

希望找到的表名 - 第三个参数 - 将映射到$3

3 个答案:

答案 0 :(得分:1)

你要求的是(大部分)不可能。 Perl不会特别处理替换字符串中的任何字符。

您可以做的是捕获(显式或隐式)匹配的文本,并使用替换部分中的一个特殊变量($1$2$&等),但这只能起作用,因为替换部分是代码。在您的情况下,s/$regexp/$newtxt/g,唯一的变量是$newtxt,其内容未重新扫描以进一步扩展。

您可以通过将带有重载字符串化的对象传递为s/$regexp/$newtxt/g来欺骗$newtxt代码,但更改代码会更好(即更容易和更易维护)。事实上,现有的代码已经有点傻了:

if ($_ !~ /$regexp/)
{
    print FOUT;
}
else
{
    s/$regexp/$newtxt/g;
    print FOUT;
}

可以简化为

s/$regexp/$newtxt/g;
print FOUT;

为了允许动态替换,自然界面是使用函数,而不是字符串:

s/$regexp/ $newtxt->() /eg;

这里/e告诉Perl,替换部分将被解析为代码块,而不是带引号的字符串。这个电话看起来像是

perl_swap( 'drop table (.*);' , sub { "echo $1;" } );

$1是第一个捕获组( )的内容。

另一方面,如果接口必须仅使用字符串,则需要进行更多的手动工作或使用为您执行此操作的模块。例如:

use Data::Munge qw(replace);
...
$_ = replace($_, $regexp, $newtxt, 'g');

这允许调用表单

perl_swap( 'drop table (.*);' , 'echo $1;' );

因为Data::Munge::replace在替换字符串中显式扫描并展开$序列,例如$1

答案 1 :(得分:1)

您正在寻找String::Substitutiongsub_modify

use String::Substitution qw( gsub_modify );

my $pat = 'drop table (.*);';
my $repl = 'echo $1;';
local $_ = 'drop table foo;';
gsub_modify($_, $pat, $repl);
say;

答案 2 :(得分:0)

我认为这会做你想要的。

    #!/usr/bin/env perl

    # always use these two
    use strict;
    use warnings;

    # use autodie to automatically die on open errors
    use autodie;

    my $s = 'drop table FOO';
    print "$s\n";

    if( $s =~ s/^drop table (.*)/exec rename_table('&')/ ){
        my $captured = $1;
        $s =~ s/\&/$captured/;
    }

    print "$s\n";