如何检测我在Perl中处理哪一行?

时间:2009-09-30 07:29:52

标签: regex perl

有一个看起来像的文本文件:

    200.0     250.0     300.0     350.0     400.0  
162:02:10 017:01:56 017:08:18 011:16:22 008:40:18
    580.0     600.0     620.0     640.0     660.0   
004:04:01 001:47:27 007:25:29 017:44:53 003:07:34

尝试解析第1行和第1行3为“值”,第2行为& 4作为“时代”。

我的代码:

if($line =~ /^\d[^:]*\d/){
     my @values = split(/\s/,$line);
        }
elsif($line =~/^\d+:\d+:\d+/){
     my @time = split(/\s/,$line);
}

问题: 始终匹配第一个正则表达式。我对正则表达式#1的理解是它会匹配一个以数字开头的行,后跟任何非“数字”的值,后跟另一个数字。

6 个答案:

答案 0 :(得分:6)

这是因为第2行和第4行确实包含第一个正则表达式的模式。

也许您只需检查一条线是否有冒号,这就足够了?像这样:

my @time;
my @values;
if($line =~ /:/){
     @time = split(/\s+/,$line);
}
else{
     @values = split(/\s+/,$line);
}

答案 1 :(得分:2)

你的第一个正则表达式每次匹配的原因是它检测到任何以数字开头的字符串可以包含任意数量的字符(除了:)然后有另一个数字。这意味着第2行将匹配冒号前的前三个字符。

您可能希望在该行的末尾匹配,或者做一些更简单的事情,比如只是匹配冒号。

答案 2 :(得分:1)

第1行和第3行满足以下正则表达式:

(?m)^(?:\s*\d+\.\d+\s*)+$

试试这个:

open(FILE, 'yourfile.txt') or die("Could not open file!");
foreach $line (<FILE>) {
  if($line =~ /(?m)^(?:\s*\d+\.\d+\s*)+$/) {
    print $line; 
  }
}

答案 3 :(得分:1)

其他答案都集中在正则表达式上。但还有另一种方法可以告诉你文件中的位置。

如果您确定这些行始终是交替的,并且顺序相同,则可以使用$.来获取您正在处理的行号。

这只适用于 values 在奇数行上始终,并且 times <在偶数行上强>总是。

my @times_and_values;
my $values; 
while(  my $line = <DATA> ) {

    if( $. % 2 ) {
        $values = parse_values($line);
    }
    else {
        my $times = parse_times($line);

        push @times_and_values, [$times, $values]
            if defined $values and defined $times;

    }

}

然后,您的解析函数可以处理行的验证和分解。使用为每个定制的正则表达式来拒绝不正确的值并进行任何解析。您可以抛出致命错误或发出警告。上面的代码将跳过时间/值对,其中任何一部分都无法解析。

答案 4 :(得分:0)

只需更改支票的顺序:

if($line =~/^\d+:\d+:\d+/){
     ...
        }
elsif($line =~ /^\d[^:]*\d/){
    ... 
}

答案 5 :(得分:-1)

if($line =~/\^d+:\d+:\d+/){
  my @values = split /\s+/, $line;
}else{
  my @time = split /\s+/, $line;
}