匹配所有数字

时间:2013-07-31 11:28:28

标签: regex perl

我在另一个话题中询问了匹配123这样的数字。这太狭隘了,随着我对Regex的深入了解,我发现你真的需要定义任何东西。所以我要求指数表示法并在this post中得到答案:/^keyword\s+(-?(?:\d+|\d*\.\d*)(?:[Ee]-?(?:\d+|\d*\.\d*))?)/。我试图理解这一点但到目前为止失败了。

所以我现在要求更具体。我需要匹配数字,我在这里给出一些例子:

13
-999
83.12300
.151
-.213
1e14
124e2
-9e-4

你得到了它,常规数学。

更具体地说,我为你提供了我的Perl代码。我在一行上搜索keyword,需要从这一行获取一个值。我想在一个正则表达式中获得此值,因为我使用or-statement ||的解决方法似乎会导致问题。

my $value;
open(FILE,"data.dat") or die "error on opening data: $!\n";
while (my $line = <FILE>) {
        if (($line =~ /^keyword\s+(-?(?:\d+|\d*\.\d*)(?:[Ee]-?(?:\d+|\d*\.\d*))?)/x) || ($line =~ /^keyword\s*(\d*\.\d*)/)) {
                $value = $1;
        };
}
close(FILE);

修改

到目前为止所有提示都是如此。

4 个答案:

答案 0 :(得分:2)

转到cpan并获取Regexp::Common

像这样使用

use Regexp::Common;

my $re = $RE{num}{real};

if ( $line =~ /^keyword\s+($re)/ ) {
  $value = $1;
}

比自己动手正则表达式滚动容易得多。

答案 1 :(得分:1)

代码中的第二个正则表达式似乎是多余的,您可以安全地删除它。第一个正则表达式应匹配所有测试用例。有什么似乎没有合作吗?

您还应该调整正则表达式,因为它目前认为-.e-.是一个数字。这来自\d*\.\d*匹配.。您可以尝试使用(?:\d+(?:\.\d*)?|\.\d+)代替您拥有的内容,它可以匹配1)数字,2)数字后跟小数,可能更多数字,或3)小数后跟数字。

答案 2 :(得分:1)

还有另一种方法可以做到这一点,你不需要正则表达式。您可以使用Scalar::Util

中的looks_like_number

以下是一个例子:How do I tell if a variable has a numeric value in Perl?我在这里粘贴了它。


示例:

#!/usr/local/bin/perl

use warnings;
use strict;

use Scalar::Util qw(looks_like_number);

my @exprs = qw(1 5.25 0.001 1.3e8 foo bar 1dd);

foreach my $expr (@exprs) {
    print "$expr is", looks_like_number($expr) ? '' : ' not', " a number\n";
}

给出这个输出:

1 is a number
5.25 is a number
0.001 is a number
1.3e8 is a number
foo is not a number
bar is not a number
1dd is not a number

编辑:@ borodin的评论

你会以这样的方式使用它:

my $value;
open(FILE,"data.dat") or die "error on opening data: $!\n";
while (my $line = <FILE>) {
        if (($line =~ /^keyword +(.*)/)) {
             my $number = $1;
             if ( looks_like_number($number) ) { 
                 $value = $number;
             }
        };
}

编辑:如果你必须有一个正则表达式,你可以使用这样的表达式:

 #!/bin/perl
 use strict;
 use warnings;

 my @numbers = ( 'keyword 13',
                 ' word   25',
                 'keyword -999',
                 'keyword 83.12300',
                 'keyword  .151',
                 'keyword -.213',
                 'keyword 1e14',
                 'keyword 124e2',
                 'keyword -9e-4 ',
                 ' keyword  e43e',
                 'keyword 4.5.6',
                 'keyword 4..e',
                 'keyword NaN',
                 'keyword Inf');

 for (@numbers) {

      if ( /^keyword +(-?((\d+\.?\d*)|(\d*\.?\d+))([Ee]-?\d+)?)/ ) {

         print "$1 is a number\n";

     } else {
         print "$_ does not match keyword or is not a number\n";
     }

 }

答案 3 :(得分:0)

感谢您提供的信息性帖子以及我在最后几天阅读的内容,我能够更多地了解正则表达式结构。所以对于这个相当简单的任务,我不想使用额外的模块/包,并希望坚持使用正则表达式。我做了一些测试和更改,以省去冗余并适应我的任务。所以我不会在一行上有几个数字,并且行上可能有空格。此外,数字的结尾由分号定义。总结一下,我发布了我的最终代码。谢谢大家的帮助。

#!/usr/bin/perl

use strict;
use warnings;

my @numbers=(
"keyword 152;",
"keyword 12.23;",
"keyword -2.001;",
"keyword .123;",
"keyword -12.;",
"keyword 55.44.33;",
"keyword 3e14;",
"keyword -3.000e0014;",
"keyword 5e-04;",
"   keyword     5e-04;  ",
"keyword 5e-04  ;",
"keyword .1e2;",
"keyword 9.e3;",
"keyword -0.01E-03;",
"keyword 1.3e-03;",
"keyword 1dd;",
"keyword -12E3e1;",
"keyword -.e.;",
"keyword -.e-.;");

for (@numbers) {

if (    /\s* keyword \s+        # stuff before matched number
    ( -?            # optional minus sign
      (?:           # no saving of group in brackets
        (?:\d+\.?\d*)       # match trailing digit and possible floating point number
        |           # or
        (?:\.\d+)       # no trailing digit and forced fpn
      )
    (?:[Ee]-?\d+)?      # optional exponential notation
    )           # end of group to be matched
    ;\s*            # stuff after matched number
    /x) {

print "<<__$_\__>>\n\t $1 \n";
} else { 
print "<<__$_\__>>\n\t !!!!! no matching here !!!!!\n";
}
}

输出:

<<__keyword 152;__>>
     152 
<<__keyword 12.23;__>>
     12.23 
<<__keyword -2.001;__>>
     -2.001 
<<__keyword .123;__>>
     .123 
<<__keyword -12.;__>>
     -12. 
<<__keyword 55.44.33;__>>
     !!!!! no matching here !!!!!
<<__keyword 3e14;__>>
     3e14 
<<__keyword -3.000e0014;__>>
     -3.000e0014 
<<__keyword 5e-04;__>>
     5e-04 
<<__    keyword     5e-04;  __>>
     5e-04 
<<__keyword 5e-04   ;__>>
     !!!!! no matching here !!!!!
<<__keyword .1e2;__>>
     .1e2 
<<__keyword 9.e3;__>>
     9.e3 
<<__keyword -0.01E-03;__>>
     -0.01E-03 
<<__keyword 1.3e-03;__>>
     1.3e-03 
<<__keyword 1dd;__>>
     !!!!! no matching here !!!!!
<<__keyword -12E3e1;__>>
     !!!!! no matching here !!!!!
<<__keyword -.e.;__>>
     !!!!! no matching here !!!!!
<<__keyword -.e-.;__>>
     !!!!! no matching here !!!!!

PS:我已经读过?:在代码运行时可能无法保存资源,这使得正则表达式对眼睛不太友好,所以可能会将其排除在外。