搜索substring并将字符串的另一部分存储为perl中的变量

时间:2017-05-19 05:06:31

标签: regex perl substring

我正在修改旧的邮件工具并添加MIME支持。我有很多工作,但我是一个perl假人和正则表达式的东西正在失去我。

我有:

foreach ( @{$body} ) {

   next if /^$/;

   if ( /NEMS/i ) {
      /.*?(\d{5,7}).*/;
      $nems = $1;
      next;
   }

   if ( $delimit ) {
      next if (/$delimit/ && ! $tp);
      last if (/$delimit/ && $tp);

      $tp = 1, next if /text.plain/;
      $tp = 0, next if /text.html/;
      s/<[^>]*>//g;
      $newbody .= $_ if $tp;
   } else {
      s/<[^>]*>//g;
      $newbody .= $_ ;
   }
}  # End Foreach

现在我感谢MIME::Parser $body_text作为纯文本邮件正文。所以现在我只需要这个部分就可以了:

foreach ( @{$body_text} ) {

   next if /^$/;

   if ( /NEMS/i ) {
      /.*?(\d{5,7}).*/;
      $nems = $1;
      next;
   }
}  # End Foreach

实际的挑战是找到NEMS=12345NEMS=1234567并设置$nems=12345(如果找到)。我认为我的测试有一个非常基本的语法问题,因为我没有经常暴露于perl。

一位同事建议:

foreach (split(/\n/,$body_text)){

    next if /^$/;

    if ( /NEMS/i ) {
        /.*?(\d{5,7}).*/;

        $nems = $1;
next;

    }
}

这似乎有效,但它可能不是首选方式?

编辑:

所以这是基于此处提示和测试的最新版本:

foreach (split(/\n/,$body_text)){

    next if /^$/;

    if ( /NEMS/i ) {
        /^\s*NEMS\s*=\s*(\d+)/i;

        $nems = $1;
    next;

    }
}

1 个答案:

答案 0 :(得分:-1)

将最后两位数字匹配为可选项并捕获前五位数字,并直接指定捕获

($nems) = /.*? (\d{5}) (?: \d{2} )?/x;  # /x allows spaces inside

构造(?: )仅对内部的内容进行分组,而不进行捕获。 ?之后的意思是匹配零次或一次。我们需要parens,以便它仅适用于该子模式。所以最后两位数字是可选的 - 五位数或七位数匹配。我还在最后删除了不需要的.*

然而,按照你所说的,似乎整个事情可以简化

if ( ($nems) = /^\s*NEMS \s* = \s* (\d{5}) (?:\d{2})?/ix ) { next }

现在不需要if (/NEMS/),我已经调整了NEMS在开头的澄清,并且=周围可能有空格。然后你也可以说

my $nems;

foreach ( split /\n/, $body_text ) {
    # ...
    next if ($nems) = /^\s*NEMS\s*=\s*(\d{5})(?:\d{2})?/i;
    # ...
}

包括澄清新$body_text是多行字符串的内容。

很明显,$nems被声明(需要)之外的循环,我指出了。

这允许更多数字跟随;它也将匹配8位数字(但只捕获前5位)。这就是正则表达式中的尾随.*所暗示的内容。

编辑已经澄清,只能有5位或7位数字。然后可以收紧正则表达式,以检查输入是否符合预期,但它也应该按原样运行。

一些注意事项,如果有更多信息可以告诉我

  • 匹配运算符返回一个列表,因此我们需要 ($nems) = /.../;中的parens

  • 对于($nems) = /.../($nems) = $_ =~ /.../;语法是一个不错的快捷方式 如果你匹配$_以外的变量,那么你需要完整的东西。

  • 总是希望用

    启动Perl程序
    use warnings 'all';
    use strict;
    

    这直接有助于并且通常会产生更好的代码。

对演化问题理解的澄清说明=之后的所有数字都需要被捕获到$nems(并且可能有5个,(不是6个),7,8,9,10个数字) 。那么正则表达式就是

($nems) = /^\s*NEMS\s*=\s*(\d+)/i;

其中\d+表示一位数,一次或多次。所以是一串数字(如果没有则匹配失败)。