正则表达式范围运算符

时间:2011-09-11 01:09:02

标签: regex perl

我有一个字符串'11 15'。 W / a Regex然后比较该字符串中的值,在本例中为11和15(可以是任意数字的数字,但我会用2个2位数字保持简单)。

对于这些数字中的每一个,我看看它是否与我想要的任何数字相匹配;在这种情况下,我想看看数字是“12”,“13”还是“14”。如果是,那么我改变'$ m'的值:

my $string = '11 15 ';
while ( $string =~ /([0-9]{1,})\s+/ig ) {
    my $m = $1;
    print $m . ".....";
    $m = 'change value' if $m =~ /[12...14]{2,}/g;
    print $m . "\n";
}

产地:

11.....change value
15.....15

'15'保持不变,应该如此。但'11'的变化。我做错了什么?

3 个答案:

答案 0 :(得分:4)

[12...14]与“1”,“2”,“。”和“4”匹配。 “11”匹配; “15”没有。如果您只是匹配数字,则不应使用正则表达式。将您的行更改为以下内容:

$m = 'change value' if $m ~~ [11..14];

或者,如果无法保证perl> = v5.10:

$m = 'change value' if grep { $m == $_ } 11..14;

答案 1 :(得分:4)

你误解了正则表达式。在您写[12...14]{2,}的地方,这意味着“匹配2个或更多字符1或2或点或点或点或点或1或4”。

尝试类似:

$m='change value' if $m=~/(\d{2,})/ and $1 >= 12 and $1 <= 14;

在替换操作中,这可以写成:

$m =~ s/(\d{2,})/ $1 >= 12 && $1 <= 14 ? 'change value' : $1/ge;

也就是说,捕获2位或更多位数,然后通过在替换的替换部分中使用perl代码来测试您捕获的内容,以查看它们是否是您想要更改的内容。 e修饰符表示Perl应将替换值评估为Perl代码。

答案 2 :(得分:0)

让我们重写一下你的代码:

my $string = '11 15 ';
while ( $string =~ /(\d+)/g ) {

我已经更改了while语句的正则表达式。您可以使用\d+来表示一个或多个数字,这比[0-9]{1,}更容易理解。您也(因为空格不匹配\d)不需要字符串末尾的最后一个空格。

让我们看一下代码的其余部分:

my $string = '11 15';
while ( $string =~ /(\d+)/g ) {
    my $match = $1;
    print "$match.....";
    if ($match >= 12 and $match <= 14) {   #if ($match ~~ [12..14]) for Perl > 5.10
        print 'change value\n';
    }
    else {
        print "$match\n";
    }
}

您不能像测试范围那样使用正则表达式。

相反,请使用

的常规范围测试
if ($match >= 12 and $match <= 14)

或较新的组测试

if ($match ~~ [12..14])  #Note only two dots and not three!

最后一个版本仅适用于我在Mac上的新版Perl,如5.12,而我的Linux机箱上有5.14,但不是我在Solaris机箱上的Perl 5.8。

一些提示:

  • 使用缩进和空格。它使您的代码更具可读性。
  • 为变量使用描述性名称。我使用了$m
  • 而不是$match
  • 请勿使用附加的if语句。附加的if更难以发现,因此您可能会错过重要的内容,这会使您的代码更难更新。如果语句本身清晰简单,并且提高了可读性,则可以使用它。最后一点有点主观,但您通常会在if之类的内容中看到附加的return if not -f $file;语句。
  • 保持变量单一用途。在这种情况下,我使用了$match语句,而不是更改if/else的值。想象一下,如果你的代码有点复杂,有人必须添加一个新功能。他们看到$match变量并认为这是他们需要的。不幸的是,您更改了$match的内容。它现在是要打印的值而不是字符串匹配。可能需要一段时间才能改变你的程序的人才能弄清楚$match的价值发生了什么,以及为什么它被神秘地设置为changed value
  • 在print语句中,您可以在双引号内包含变量。这与几乎所有其他语言非常不同。这是因为Perl变量使用sigils来标记变量名称。如果将变量和其他字符串组合在一个字符串中,通常会更容易阅读。

例如:

 print "The range of possible values are $low to $high\n";

VS

 print "The range of possible values are " . $low . " to " . $high . "\n";

请注意,在第二个示例中,我必须小心引号内的空格,而在第一个示例中,所需的空格相当自然。想象一下,必须在程序的更高版本中更改该语句。哪个更容易维护?