【问题标题】:Matching modifying characters after pattern匹配模式后的修改字符
【发布时间】:2016-10-05 17:19:20
【问题描述】:

我大约在 20 年前就这样做了,所以我已经忘记了很多关于 Perl 的事情,而且我没有从 Google 那里找到答案。

我有一个包含许多 Times Ten DB create hash index 形式的语句的文件

create unique hash index on MYSCHEMA.MYTABLE (Col1, Col2)  pages=####;
create hash index on MYSCHEMA.ANOTHER_TABLE (Col1, Col2)  pages=####;

我有一个由表名作为键的散列,其中包含“pages=###”所需的值。

我已经正确地将该行读入一个字符串变量,我需要知道如何将index on MYSCHEMA. 后面的表名放入一个变量中。

另外,如何替换pages=####中的数字?

【问题讨论】:

    标签: perl


    【解决方案1】:

    在列表上下文中使用匹配来提取表名。

    #!/usr/bin/perl
    use warnings;
    use strict;
    
    my @lines = (
        "create unique hash index on MYSCHEMA.MYTABLE (Col1, Col2)  pages=####;\n",
        "create hash index on MYSCHEMA.ANOTHER_TABLE (Col1, Col2)  pages=####;\n"
    );
    
    my %pages = ( MYTABLE => 12,
                  ANOTHER_TABLE => 42,
    );
    
    for my $line (@lines) {
        my ($table) = $line =~ /index on MYSCHEMA\.(\w+)/;
        $line =~ s/pages=####/pages=$pages{$table}/;
        print $line;
    }
    

    【讨论】:

      【解决方案2】:

      提取架构名称

      my ($schema_name) = $line =~ s/MYSCHEMA\.([A-Z_]+)/;
      

      替换pages=后面的数字

      $line =~ s/(pages=)(#+)/$1$number_replacement/;
      

      这适用于对行结构的一些假设 - 架构名称仅包含大写字母或下划线,并且数字跟在 = 后面不带空格。


      更好的方法,由Borodin在评论中提供

      $line =~ s/pages=\K#+/$number_replacement/;

      \K正向后视(?<=pattern) 的一种特殊形式,它是一个零宽度断言,即给定模式在当前匹配位置之前。这种形式还会丢弃所有以前的匹配项,因此上面的替换不会触及pages= 部分。因此不需要任何捕获组。请参阅环视断言 in perlretut\K in perlre(向下滚动一点)。

      【讨论】:

      • s/pages=\K#+/$number_replacement/
      • @Borodin 哦,是的,太棒了 :) \K 的完美用途——也可以清理它!
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2013-12-05
      • 1970-01-01
      • 1970-01-01
      • 2012-08-22
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多