【问题标题】:Perl while loop when parse a string解析字符串时的Perl while循环
【发布时间】:2013-10-25 04:57:26
【问题描述】:

我收到一个关于解析向量的问题,其中包含如下字符串:

"chr1-247751935-G-.:M92R,chr1-247752366-G-.:R236G,"
"chr1-247951785-G-.:G98K,"
"chr13-86597895-S-78:M34*,chr13-56891235-S-8:G87K,chr13-235689125-S-7:M389L,"

我想得到:

"M92R R236G"
"G98K"
"M34* G87K M389L"

当我使用时

while ($info1=~s/^(.*)\:(([A-Z\*]){1}([\d]+)([A-Z\*]){1})\,//) 
{
    $pos=$2; 
}

结果$pos只给我每一行的最后一个,即:

"R236G"
"G98K"
"M389L"

我应该如何更正脚本?

【问题讨论】:

  • 欢迎来到 Stack Overflow。请尽快阅读 [bout] 页面。请注意,通过选择行,然后使用编辑框上方的 {} 按钮将其缩进,它有助于将代码(通常也是数据)格式化为“代码”。
  • {1} 符号不是必需的;可以在不更改正则表达式的情况下省略它(因为没有它,之前的模式将需要一次)。

标签: regex perl while-loop


【解决方案1】:

您的代码不起作用的原因是您在正则表达式的开头有一个 greedy ^(.*)。只要其余的模式匹配,这将尽可能多地占用目标字符串,因此您只会找到子字符串的 last 出现。您可以通过将其更改为非贪婪模式 ^(.*?) 来修复它。

关于您的正则表达式的一些其他说明:

  • :,* 在字符类 [...] 内时无需转义

  • 永远不需要量词 {1},因为这是没有量词的模式的效果

  • 无需将\d 放在字符类[\d] 中,因为它本身就可以正常工作

  • 没有必要将子模式括在括号中,除非您需要在匹配成功时访问与该子模式匹配的任何子字符串。因此,例如 ^.* 没有括号就可以了

您的代码修改与您的代码相同,但更加简洁

while ($info1 =~ s/^.*?:([A-Z*]\d+[A-Z*]),// ) {
  my $pos = $1;
  ...
}

但最好的解决方案是使用 全局 匹配来查找字符串中所有出现的模式,并且不需要在此过程中修改字符串。

该程序执行您所描述的操作。它只查找每条记录中冒号后面的所有字母数字或星号字符串。

use strict;
use warnings;

while (<DATA>) {
  my @fields = /:([A-Z0-9*]+)/g;
  print "@fields\n";
}

__DATA__
"chr1-247751935-G-.:M92R,chr1-247752366-G-.:R236G,"
"chr1-247951785-G-.:G98K,"
"chr13-86597895-S-78:M34*,chr13-56891235-S-8:G87K,chr13-235689125-S-7:M389L,"

输出

M92R R236G
G98K
M34* G87K M389L

【讨论】:

  • 您好,我尝试了您根据我的脚本更正的那个,但它仍然显示与我之前得到的相同的内容。你能帮我解决这个问题吗?由于我对 perl 还很陌生,所以我不太明白如何将您提供的新版本放入我的脚本中。非常感谢。
【解决方案2】:

使用单线:

$ perl -ne 'print q/"/ . join(" ", m/:([^,]+),/g) . qq/"\n/' file
"M92R R236G"
"G98K" 
"M34* G87K M389L"

在脚本中:

$ perl -MO=Deparse -ne 'print "\042" . join(" ", m/:([^,]+),/g) . "\042\n"' file

脚本:

LINE: while (defined($_ = <ARGV>)) {
    print '"' . join(' ', /:([^,]+),/g) . qq["\n];
}

【讨论】:

    【解决方案3】:

    您可以将冒号和一些字母数字字符用作正则表达式,使用数组保存它们并在循环结束时打印。这里有一个例子:

    #!/usr/bin/env perl;
    
    use strict;
    use warnings;
    
    my (@data);
    
    while ( <DATA> ) { 
        while ( m/:([[:alnum:]*]+)/g ) { 
            push @data, $1; 
        }   
        printf qq|"%s"\n|, join q| |, @data;
        undef @data;
    }
    
    __DATA__
    "chr1-247751935-G-.:M92R,chr1-247752366-G-.:R236G,"
    "chr1-247951785-G-.:G98K,"
    "chr13-86597895-S-78:M34*,chr13-56891235-S-8:G87K,chr13-235689125-S-7:M389L,"
    

    像这样运行它:

    perl script.pl
    

    产生:

    "M92R R236G"
    "G98K"
    "M34* G87K M389L"
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2014-07-19
      • 1970-01-01
      • 2012-03-09
      • 2015-03-11
      • 2015-03-25
      • 1970-01-01
      • 2021-06-17
      • 2013-06-22
      相关资源
      最近更新 更多