6

次の文字列の空の「フィールド」の数を数えるにはどうすればよいですか? 空のフィールドは-|or|-|またはで示されます|- 私が作成した正規表現は、空のフィールドが連続している場合を除いて機能しているようです ? 貪欲にならないようにするにはどうすればよいですか?

my $string = 'P|CHNA|string-string|-|-|25.75|-|2562000|-0.06';
my $count = () = ($string=~/(?:^-\||\|-$|\|-\|)/g);   
printf("$count\n");

上記のコードは、私が望む 3 ではなく 2 を出力します。

4

3 に答える 3

7

これについては正規表現ルートを完全に避け、代わりにこれをリストのように扱います。

my $count = grep { /^-$/ } split /\|/, $string;
于 2013-10-16T21:21:03.067 に答える
3

この問題は、実際には貪欲/怠惰とは何の関係もありません(*またはのような繰り返し演算子にのみ適用されます+)。

問題は、2 つの空のフィールドが隣り合っていることです: |-|-|. |最初のものは一致していますが、オープニングがすでに消費されているため、2 番目のものは失敗しますが、ルールに行頭マーカーがあるため^-|、それは一致しません。

|はるかに簡単なアプローチは、入力を分割してから、 a のみで構成されるフィールドを探すことだと思います-

my $count = 0;
foreach (split(/\|/,$string)) { if( /^-$/ ) { $count++; } }

Perl は可変長の後読みをサポートしていないため (少なくとも私の知る限り)、これを正規表現で確実に実装する方法はありません。「チート」する 1 つの方法|は、最初と最後に a を追加することです。そうすれば、後読み/先読みアサーションをうまく使用できます。

$string = "|$string|";
my $count = () = $string=~/(?<=\|)-(?=\|)/g;

(以下の池釜の回答には、文字列を変更せずに非変数ルックアラウンドアサーションを使用する代替ソリューションがあるため、「正規表現でこれを実装する方法がない」と言ったのは間違っていました。池釜への小道具。私はまだ分割を考えています|ただし、この問題を解決するには最善の方法です。)

于 2013-10-16T21:14:19.463 に答える
2

トリックは、ルックアラウンドを使用することです。誰かの最初の試みは次のようなものかもしれません:

my $count = () = $string =~ /
   (?<\|)  # Preceded by "|"
   (-)
   (?=\|)  # Followed by "|"
/xg;

しかし、それはうまくいきません。上記の問題は、最初のフィールドまたは最後のフィールドが空であるかどうかを検出できないことです。それを修正する2つの方法:

my $count = () = "|$string|" =~ /
   (?<\|)  # Preceded by "|"
   (-)
   (?=\|)  # Followed by "|"
/xg;

また

my $count = () = $string =~ /
   (?<![^|])  # Not preceded by a char other than "|"
   (-)
   (?![^|])   # Not followed by a char other than "|"
/xg;
于 2013-10-16T21:27:11.297 に答える