3

次のコードがあります。

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

my $SourceStr='Foo - Name: Rob  Time: 11/2/2011 13:47:30  State: Prelim 3  Optional: Some stuff here';
#my $SourceStr='Foo - Name: Rob  Time: 11/2/2011 13:47:30  State: Prelim 3';

my $RegEx = qr/Name: (.+)  Time: (.+)  State: (.+)  Optional: (.+?)(  |$)/;

if ($SourceStr =~ m/$RegEx/) {
   print "1=[$1]\n";
   print "2=[$2]\n";
   print "3=[$3]\n";
   print "4=[$4]\n";
}

最初の $SourceStr で実行すると、期待どおりに動作します。ただし、コメント アウトされている 2 番目の場合、$4 に空の文字列を入力する方法はありますか?

最初の文字列の結果:

1=[Rob]
2=[11/2/2011 1:47:30 PM]
3=[3]
4=[Some stuff here]

2 番目の文字列の結果: 一致しません

欲しい:

1=[Rob]
2=[11/2/2011 1:47:30 PM]
3=[3]
4=[]
4

5 に答える 5

2

より具体的な正規表現を使用できます。

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

my @SourceStrA=('Foo - Name: Rob  Time: 11/2/2011 13:47:30  State: 3  Optional: Some stuff here',
                'Foo - Name: Rob  Time: 11/2/2011 13:47:30  State: 3');

my $RegEx = qr!Name:\s*(\w+)\s*Time:\s*([\d/]*\s*[\d:]*)\s*State:\s*(\d+)\s*(?:Optional:\s*(.*))?!;

for my $SourceStr (@SourceStrA) {
  print "$SourceStr\n";
  if ($SourceStr =~ m/$RegEx/) {
    print "1=[$1]\n";
    print "2=[$2]\n";
    print "3=[$3]\n";
    print "4=[$4]\n" if defined $4; 
  }
}

出力:

Foo - Name: Rob  Time: 11/2/2011 13:47:30  State: 3  Optional: Some stuff here
1=[Rob]
2=[11/2/2011 13:47:30]
3=[3]
4=[Some stuff here]
Foo - Name: Rob  Time: 11/2/2011 13:47:30  State: 3
1=[Rob]
2=[11/2/2011 13:47:30]
3=[3]
于 2013-01-04T22:19:04.800 に答える
1

hereに記載されているように、番号付きではなく名前付きキャプチャを介してオプションの一致を処理する方が簡単な場合があります。

#!/usr/bin/env perl

use warnings;
use strict;

my @SourceStr = (
  'Foo - Name: Rob  Time: 11/2/2011 13:47:30  State: 3  Optional: Some stuff here',
  'Foo - Name: Rob  Time: 11/2/2011 13:47:30  State: 3',
);

my $RegEx = qr/Name: (?<name>.+?)  Time: (?<time>.+?)  State: (?<state>.+?)(?:  Optional: (?<optional>.+?))?(  |$)/;

foreach (@SourceStr) {
  print "Input '$_'\n";
  if ( /$RegEx/ ) {
     print "Name = '$+{name}'\n";
     print "Time = '$+{time}'\n";
     print "State = '$+{state}'\n";
     print "Optional = '$+{optional}'\n" if $+{optional};
  }
  print "\n";
}

%+実際、ハッシュをダンプするだけで、非常に簡単になります。

#!/usr/bin/env perl

use warnings;
use strict;

my @SourceStr = (
  'Foo - Name: Rob  Time: 11/2/2011 13:47:30  State: 3  Optional: Some stuff here',
  'Foo - Name: Rob  Time: 11/2/2011 13:47:30  State: 3',
);

my $RegEx = qr/Name: (?<name>.+?)  Time: (?<time>.+?)  State: (?<state>.+?)(?:  Optional: (?<optional>.+?))?(  |$)/;

use Data::Dumper;
foreach (@SourceStr) {
  print "Input '$_'\n";
  print Dumper \%+ if /$RegEx/;
}
于 2013-01-05T01:54:58.450 に答える
1

リクエストは奇妙に思えますが、解決策は次のとおりです。

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

my $SourceStr='Foo - Name: Rob  Time: 11/2/2011 13:47:30  State: 3  Optional: Some stuff here';
#my $SourceStr='Foo - Name: Rob  Time: 11/2/2011 13:47:30  State: 3';

my $RegEx = qr/Name: (.+)  Time: (.+)  State: (.+?)(?:  Optional: )?(.*)(  |$)/;

if ($SourceStr =~ m/$RegEx/) {
   print "1=[$1]\n";
   print "2=[$2]\n";
   print "3=[$3]\n";
   print "4=[$4]\n";
}

秘訣はもちろん、(?: )構文を使用して、$4 の場所を変更せずに追加のグループを作成することでした。(?: Optional: (.*))?また、 $4 が未定義になることを意味し (そして空の文字列である必要がある)、use strictプラグマが不穏なUse of uninitialized value...メッセージを出力しているため、 usingは正しくありません (より論理的で堅牢ですが)。

とにかく、これらの要件は実際の問題というよりは演習のように見えますね。

于 2013-01-04T22:48:00.080 に答える
1

たぶん、ハッシュか何かを使用する必要があります。

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

#my $SourceStr='Foo - Name: Rob  Time: 11/2/2011 13:47:30  State: 3  Optional: Some stuff here';
my $SourceStr='Foo - Name: Rob  Time: 11/2/2011 13:47:30  State: 3';

my %Values;

while ($SourceStr =~ m/(\w+): (.+?)(?:  |$)/g) {
    $Values{$1} = $2;
}

if ($Values{Name} && $Values{Time} && $Values{State}) {
    print "1=$Values{Name}\n";
    print "2=$Values{Time}\n";
    print "3=$Values{State}\n";

    if (defined $Values{Optional}) {
        print "4=$Values{Optional}\n";
    } else {
        print "4=\n";
    }
}
于 2013-01-04T22:34:03.703 に答える