如何在perl中使用正则表达式0或数字

时间:2013-11-26 12:55:05

标签: regex perl

我正试着从我文件中的以下行中捕获以下内容:

1.39223 0.303787
71.9792 0

输入文件(示例):

XLOC_000559 XLOC_000559 -   S3603:13352-18211   con exp OK  1.39223 0.303787    -2.19627    -1.93877    0.0001  0.0140909   yes
XLOC_001511 XLOC_001511 -   S7778:1319-1421 con exp OK  71.9792 0   -inf    -nan    0.00035 0.0365407   yes

我试过了正则表达式:

my ($con_val, $expt_val) = ($1, $2) if ($_ =~ /OK\t(\d+\.\d+)\t(\d+\.\d+)/);

但它没有处理0值......

有人可以帮忙吗?

5 个答案:

答案 0 :(得分:3)

几乎可以肯定无需确保您的数字最多包含一个小数点,解决此问题的最简单方法是使用匹配任何内容的字符类 [\d.]数字或点。

请注意,除非您另有说明,否则正则表达式将应用于$_,因此无需编写$_ =~

这个简短的程序可以帮到你。

use strict;
use warnings;

while (<DATA>) {
  next unless /OK\s+([\d.]+)\s+([\d.]+)/;
  my ($con_val, $expt_val) = ($1, $2);
  print "$con_val, $expt_val\n";
}

__DATA__
XLOC_000559 XLOC_000559 -   S3603:13352-18211   con exp OK  1.39223 0.303787    -2.19627    -1.93877    0.0001  0.0140909   yes
XLOC_001511 XLOC_001511 -   S7778:1319-1421 con exp OK  71.9792 0   -inf    -nan    0.00035 0.0365407   yes

<强>输出

1.39223, 0.303787
71.9792, 0

答案 1 :(得分:1)

您必须将\.\d+包含在?的括号中,以使/OK\t(\d+(?:\.\d+)?)\t(\d+(?:\.\d+)?)/ 成为可选项:

?:

open-paren之后的{{1}}会阻止正则表达式引擎在匹配结果中创建分组。

答案 2 :(得分:1)

use Regexp::Common;
my ($con_val, $expt_val) = /OK\s+ ($RE{num}{real}) \s+ ($RE{num}{real})/x;

perl -anE 'say "@F[7,8]"' file

答案 3 :(得分:0)

假设第二个值(您要捕获为'$ expt_val')后面始终跟一个制表符,这应该有效:

my ($con_val, $expt_val) = ($1, $2) if ($row =~ /OK\t(\d+\.\d+)\t(.+)\t/);

答案 4 :(得分:-1)

您应该使用或运算符|指定:

  • 一个或多个数字(\d+)后跟文字. (\.),后跟一个或多个数字(\d+)

OR

  • 文字0

试试这个:

#!/usr/bin/perl
use warnings;
use strict; 
use Data::Dumper;

my @array =('XLOC_000559    XLOC_000559 -   S3603:13352-18211   con exp OK  1.39223 0.303787    -2.19627    -1.93877    0.0001  0.0140909   yes',
    'XLOC_001511    XLOC_001511 -   S7778:1319-1421 con exp OK  71.9792 0   -inf    -nan    0.00035 0.0365407   yes');

foreach (@array){
    my ($con_val, $expt_val) = ($1, $2) if ($_ =~ /OK\t(\d+\.\d+|0)\t(\d+\.\d+|0)/); 
    print "$con_val\t$expt_val\n";
}

输出:

1.39223 0.303787
71.9792 0

或者更好的是,假设您的值以\t分隔,我会这样做:

my (@con_val, @expt_val);
foreach (@array){
    my @split = split(/\t/);
    push @con_val, $split[7];
    push @expt_val, $split[8];
}

print Dumper \@expt_val;
print Dumper \@con_val;

输出:

$VAR1 = [
          '0.303787',
          '0'
        ];
$VAR1 = [
          '1.39223',
          '71.9792'
        ];