解析字符串时Perl while循环

时间:2013-10-24 20:24:56

标签: regex perl while-loop

我得到一个关于解析向量的问题有这样的字符串:

"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"

我该如何更正脚本?

3 个答案:

答案 0 :(得分:1)

使用单行:

$ 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];
}

答案 1 :(得分:1)

您的代码无效的原因是您在正则表达式的开头有一个贪心 ^(.*)。只要模式的其余部分匹配,这将占用尽可能多的目标字符串,因此您将只找到子字符串的 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

答案 2 :(得分:0)

你可以使用冒号作为冒号和一些alpanumerics字符,使用数组来保存它们并在循环结束时打印。这里有一个例子:

#!/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"