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}1 桁ですが 2 桁までという意味だと思いました。1つまり、とのみが印刷されているはず2ですよね?

1 ~ 2 桁の項目を抽出するに何が必要ですか?

4

6 に答える 6

5

\d{1,2}指定された文字列のどこかに 1 つまたは 2 つの数字が見つかった場合、成功します。追加の文字列コンテンツは、一致が失敗する原因にはなりません。文字列に 1 桁または 2 桁の数字が含まれている場合にのみ一致させたい場合は、次のようにします。^\d{1,2}$

于 2012-01-02T02:53:14.833 に答える
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"

これにより、文字列が 3 つのセクションに分割されます。正規表現が一致する前の文字列のセクション、正規表現が一致する文字列のセクション、正規表現が一致した後の文字列のセクションです。

いずれの場合も、正規表現は文字列の先頭から一致するため、事前一致はありませんでした。\d{1,2}?また、 が 2 桁に一致した可能性がある場合でも、それぞれ 1 桁に一致することがわかり123ます。なんで?一致指定子の末尾にある疑問符は、正規表現が貪欲ではないことを示しているためです。この場合、1 つまたは 2 つの文字に一致するように正規表現を指定します。いいですね、それは 1 つに一致します。疑問符を削除すると、最後の行は次のようになります。

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

3 桁以上ではなく 1 桁または 2 桁で一致させたい場合は、文字列の 1 桁または 2 桁の前後の部分を指定する必要があります。このようなもの:

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

これは文字列と一致しますが、一致foo12barしませんfoo123bar。しかし、文字列が の場合は12どうでしょうか? その場合、1 文字または 2 文字が一致する前に文字列の先頭または非数字があり、末尾に非数字または文字列の末尾があると言いたいです。 1 文字または 2 文字の一致:

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

簡単な説明:

  • (\D|^): 数字以外または文字列の先頭 (^アンカー)
  • d{1,2}:1桁または2桁
  • (\D|$): 数字以外または文字列の末尾 ($アンカー)

さて、これは に一致しますが には一致し12ません。123また、 and には一致foo12しますが、 orには一致しfoo12barません。foo123foo123bar

1 桁または 2 桁の数字を探すだけで、アンカーを指定できます。

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

これは , に一致しますが、 orには一致112ません。foo12123

主なことは、、、および変数を使用して$`、正規表現が何に一致しているか、および一致の前後に何があるかを正確に確認できるようにすることです。$&$'

于 2012-01-02T05:08:25.607 に答える
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 に答える
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

いいえ、正規表現は 2 桁しか一致しませんが、$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 に答える
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 に答える