4

次の行があります。

"14:48 say;0ed673079715c343281355c2a1fde843;2;laka;hello ;)"

単純な正規表現を使用してこれを解析します。

if($line =~ /(\d+:\d+)\ssay;(.*);(.*);(.*);(.*)/) {
    my($ts, $hash, $pid, $handle, $quote) = ($1, $2, $3, $4, $5);
}

しかし ; 最後に物事を台無しにし、その理由がわかりません。貪欲なオペレーターは「すべて」を処理するべきではありませんか?

4

6 に答える 6

18

貪欲な演算子は、可能な限り多くのものを取得しようとしますが、それでも文字列に一致します。何が起こっているかというと、最初のもの (「say」の後) は「0ed673079715c343281355c2a1fde843;2」を取得し、2 番目のものは「laka」を取得し、3 番目のものは「hello」を見つけ、4 番目のものは括弧に一致します。

あなたがする必要があるのは、最後のものを除くすべてを貪欲でないようにすることです。

(\d+:\d+)\ssay;(.*?);(.*?);(.*?);(.*)
于 2008-11-01T17:44:16.597 に答える
7

正規表現でこれを簡単に行うことができますが、それが最も簡単な方法かどうかはわかりません。おそらく最短ですが、実際には最も保守しやすいわけではありません。

代わりに、次のようなことをお勧めします。

$x="14:48 say;0ed673079715c343281355c2a1fde843;2;laka;hello ;)";

if (($ts,$rest) = $x =~ /(\d+:\d+)\s+(.*)/)
{
    my($command,$hash,$pid,$handle,$quote) = split /;/, $rest, 5;
    print join ",", map { "[$_]" } $ts,$command,$hash,$pid,$handle,$quote
}

これにより、次の結果が得られます。

[14:48],[say],[0ed673079715c343281355c2a1fde843],[2],[laka],[hello ;)]

これで少しは読みやすくなったと思います。それだけでなく、人間がペンと紙で同じことを試みた場合の方法に近いため、デバッグと保守も容易になると思います。文字列をチャンクに分割して、簡単に解析できるようにします。コンピューターに、あなたがすることとまったく同じようにさせます。改造する時はこっちの方がいいと思います。YMMV。

于 2008-11-01T18:06:41.857 に答える
7
(\d+:\d+)\ssay;([^;]*);([^;]*);([^;]*);(.*)

うまくいくはずです

于 2008-11-01T17:40:29.087 に答える
3

セミコロンで区切られたリストの値にセミコロン自体を含めることができない場合は、それをスペルアウトするだけで、最も効率的で簡単な正規表現を取得できます。特定の値が、たとえば 16 進文字の文字列にしかならない場合は、それを綴ります。怠け者または貪欲なドットを使用したソリューションは、正規表現が対象の文字列と一致しない場合、常に多くの役に立たないバックトラッキングにつながります。

(\d+:\d+)\ssay;([a-f0-9]+);(\d+);(\w+);([^;\r\n]+)
于 2008-11-02T01:21:51.167 に答える
3

最初の 3 つを(.*)貪欲にしないでください(.*?)

于 2008-11-01T17:39:00.523 に答える
2

疑問符を追加することで、 * を非貪欲にすることができます。

$line =~ /(\d+:\d+)\ssay;(.*?);(.*?);(.*?);(.*)/

または、最後の部分を除く各部分でセミコロンを除くすべてに一致させることができます。

$line =~ /(\d+:\d+)\ssay;([^;]*);([^;]*);([^;]*);(.*)/
于 2008-11-01T17:47:39.680 に答える