8

私はこのようなテキストを持っています:

00:00 stuff
00:01 more stuff
multi line
  and going
00:02 still 
    have

ですから、私にはブロックの終わりはなく、新しいブロックの始まりだけがあります。

すべてのブロックを再帰的に取得したい:

1 = 00:00 stuff
2 = 00:01 more stuff
multi line
  and going

次のコードは私にこれを与えるだけです:

$VAR1 = '00:00';
$VAR2 = '';
$VAR3 = '00:01';
$VAR4 = '';
$VAR5 = '00:02';
$VAR6 = '';

私は何が間違っているのですか?

my $text = '00:00 stuff
00:01 more stuff
multi line
 and going
00:02 still 
have
    ';
my @array = $text =~ m/^([0-9]{2}:[0-9]{2})(.*?)/gms;
print Dumper(@array);
4

3 に答える 3

4

バージョン5.10.0では、重要なパターンの照合に役立つ名前付きキャプチャグループが導入されました。

(?'NAME'pattern)
(?<NAME>pattern)

名前付きキャプチャグループ。通常のキャプチャ括弧とすべての点で同じ()ですが、グループはさまざまな正規表現構造(など)で名前で参照でき、または\g{NAME}を介して一致した後に名前でアクセスできるという追加の事実があります。とハッシュの詳細については、perlvarを参照してください。%+%-%+%-

複数の異なるキャプチャグループが同じ名前を持っている場合$+{NAME}、は一致で左端に定義されたグループを参照します。

フォーム(?'NAME'pattern)(?<NAME>pattern)は同等です。

名前付きキャプチャグループを使用すると、次のように正規表現内のサブパターンに名前を付けることができます。

use 5.10.0;  # named capture buffers

my $block_pattern = qr/
  (?<time>(?&_time)) (?&_sp) (?<desc>(?&_desc))

  (?(DEFINE)
    # timestamp at logical beginning-of-line
    (?<_time> (?m:^) [0-9][0-9]:[0-9][0-9])

    # runs of spaces or tabs
    (?<_sp> [ \t]+)

    # description is everything through the end of the record
    (?<_desc>
      # s switch makes . match newline too
      (?s: .+?)

      # terminate before optional whitespace (which we remove) followed
      # by either end-of-string or the start of another block
      (?= (?&_sp)? (?: $ | (?&_time)))
    )
  )
/x;

のように使用してください

my $text = '00:00 stuff
00:01 more stuff
multi line
 and going
00:02 still
have
    ';

while ($text =~ /$block_pattern/g) {
  print "time=[$+{time}]\n",
        "desc=[[[\n",
        $+{desc},
        "]]]\n\n";
}

出力:

$ ./blocks-demo
時間=[00:00]
desc = [[[
もの
]]]

時間=[00:01]
desc = [[[
より多くのもの
マルチライン
 と行く
]]]

時間=[00:02]
desc = [[[
まだ
持ってる
]]]
于 2012-05-14T13:26:31.330 に答える
3

これでうまくいくはずです。次の\d\ d:\ d \ dの開始は、ブロック終了として扱われます。

use strict;

my $Str = '00:00 stuff
00:01 more stuff
multi line
  and going
00:02 still 
    have
00:03 still 
    have' ;

my @Blocks = ($Str =~ m#(\d\d:\d\d.+?(?:(?=\d\d:\d\d)|$))#gs);

print join "--\n", @Blocks;
于 2012-05-14T12:42:41.303 に答える
0

あなたの問題は、.*?貪欲であるのと同じように貪欲ではないということ.*です。強制されていない場合は、可能な限り一致しません。この場合は空の文字列です。

したがって、貪欲でない試合の後に、キャプチャを固定するために何かが必要になります。私はこの正規表現を思いついた:

my @array = $text =~ m/\n?([0-9]{2}:[0-9]{2}.*?)(?=\n[0-9]{2}:|$)/gs;

/mご覧のとおり、先読みアサーションで文字列の終わりと正確に一致できるようにするオプションを削除しました。

この解決策も検討してください。

my @array = split /(?=[0-9]{2}:[0-9]{2})/, $text;
于 2012-05-14T12:42:09.200 に答える