1

在此代码部分中考虑我的正则表达式:

use strict;

my @list = ("1", "2", "123");

&chk(@list);

sub chk {
    my @num = split (" ", "@_");
    foreach my $chk (@num) {
        chomp $chk;
        if ($chk =~ m/\d{1,2}?/) {
            print "$chk\n";
        }
    }
}

\d{4}不打印任何内容。将\d{3}仅打印123. 但是,如果我更改为\d{1,2}?它将打印所有内容。我认为,根据我目前阅读的所有资料,这{1,2}意味着:一位但不超过两位。所以它应该只打印1and 2,对吗?

我需要什么来提取包含一到两位数字的项目?

4

6 回答 6

5

\d{1,2}如果它在提供的字符串中的任何位置找到 1 或 2 位数字,则成功。额外的字符串内容不会导致匹配失败。如果您只想在字符串正好包含 1 位或 2 位数字时进行匹配,请执行以下操作:^\d{1,2}$

于 2012-01-02T02:53:14.833 回答
1

您应该锚定正则表达式以获得所需的效果。内置函数grep更适合这里,因为它是从要完成的数组中选择的:

#!/usr/bin/env perl

use strict;
use warnings;

my @list = ( 1, 2, 123 );
print join "\n", grep /^\d{1,2}$/, @list;
于 2012-01-02T04:03:25.057 回答
1

它似乎工作得很好!

这里有一个提示:使用 Perl 变量$`$&$'。这些变量是特殊的正则表达式变量,显示匹配前的字符串部分、匹配的内容和匹配后的字符串。

这是一个示例程序:

#! /usr/bin/env perl
use strict;
use warnings;
use feature qw(say);
use Scalar::Util;

my @list = ("1", "2", "123");

foreach my $string (@list) {
    if ($string =~ /\d{1,2}?/) {
        say qq(We have a match for "string"!);
        say qq("$`"  "$&"  "$'");
    }
    else {
        say "No match makes David Sad";
    }
}

输出将是:

We have a match for "1"!
""  "1"  ""
We have a match for "2"!
""  "2"  ""
We have a match for "123"!
""  "1"  "23"

这样做是将字符串分成三个部分:正则表达式匹配之前的字符串部分、匹配正则表达式的字符串部分和正则表达式匹配之后的字符串部分。

在每种情况下,都没有预匹配,因为正则表达式从字符串的开头匹配。我们还看到\d{1,2}?在每种情况下都匹配一个数字,即使123可能匹配两个数字。为什么?因为匹配说明符末尾的问号告诉正则表达式不要贪婪。在这种情况下,我们告诉正则表达式匹配一个或两个字符。好吧,它匹配一个。去掉问号,最后一行应该是这样的:

We have a match for "123"!
""  "12"  "3"

如果您想匹配一位或两位数,而不是三位或更多位,则必须指定一位或两位数之前和之后的字符串部分。像这样的东西:

/\D\d{1,2}\D/

这将匹配您的字符串foo12bar,但不匹配foo123bar。但是如果字符串是12呢?在这种情况下,我们想说要么我们有字符串的开头,要么在我们的一个或两个字符匹配之前有一个非数字,我们要么在我们的结尾有一个非数字或字符串的结尾一两个字符匹配:

/(\D|^)\d{1,2}(/D|$)/

快速解释:

  • (\D|^):非数字或字符串的开头(^锚点)
  • d{1,2}: 一位或两位数
  • (\D|$):非数字或字符串的结尾($锚点)

现在,这将匹配12, 但不匹配 ,123它会匹配foo12and foo12bar,但不匹配foo123or foo123bar

只需寻找一位或两位数,我们可以简单地指定锚点:

/^\d{1,2}$/;

现在,它将匹配1, 12,但不匹配foo12or 123

最主要的是使用$`,$&$'变量来帮助准确查看正则表达式匹配的内容以及匹配前后的内容。

于 2012-01-02T05:08:25.607 回答
0
#!/usr/bin/perl
use strict;

my @list = ("1", "2", "123");

&chk(\@list);

sub chk {

    foreach my $chk (@{$_[0]}) {
        print "$chk\n" if $chk =~ m/^\d{1,2}$/ ;        
    }
}
于 2012-01-02T03:26:40.243 回答
0
#!/usr/bin/perl
use strict;
use warnings;
my @list = ("1", "2", "123");

&chk(@list);

sub chk {
    my @num = split (" ", "@_");
    foreach my $chk (@num) {
        chomp $chk;
        if ($chk =~ m/\d{1,2}/ && length($chk) <= 2) {
            print "$chk\n";
        }
    }
}
于 2012-01-02T05:29:29.763 回答
0

不,因为虽然正则表达式只匹配两位数,$chk但仍然包含123. 如果您只想打印匹配的部分,请使用

if ($chk =~ m/(\d{1,2})/) {
    print "$1\n";
}

注意括号和 $1。这导致它只打印括号中的内容。

此外,这段代码没有多大意义:

sub chk {
    my @num = split (" ", "@_");

因为@_ 已经是一个数组,所以将它变成一个字符串然后拆分它是没有意义的。只需这样做:

sub chk {
    foreach my $chk (@_) {

您也不需要使用chomp不是来自用户输入的数据,因为它旨在删除尾随换行符。这些数据中没有换行符。

于 2012-01-02T02:39:54.683 回答