Frage

    

Diese Frage bereits eine Antwort hier:

         

Ich habe die folgende Zeile:

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

ich analysieren diese durch eine einfache regexp mit:

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

Aber das; am Ende vermasselt Dinge und ich weiß nicht, warum. Sollte nicht der gierige Bedienhebel „alles“?

War es hilfreich?

Lösung

Der gierige Operator versucht, so viel Zeug zu packen, wie es kann und immer noch mit der Zeichenfolge übereinstimmen. Was geschieht, ist die erste (nach „sagen“) packt „0ed673079715c343281355c2a1fde843; 2“., Die zweite nimmt „Laka“, das dritte „Hallo“ findet und die vierte bringt die Klammern

Was Sie tun müssen, ist alle, aber die letzte nicht-gierig zu machen, so greifen sie so wenig wie möglich und immer noch mit der Zeichenfolge übereinstimmen:

(\d+:\d+)\ssay;(.*?);(.*?);(.*?);(.*)

Andere Tipps

(\d+:\d+)\ssay;([^;]*);([^;]*);([^;]*);(.*)

sollte besser funktionieren

Obwohl ein regex dies leicht tun können, ich bin nicht sicher, ob es das Straight-Forward-Ansatz ist. Es ist wahrscheinlich der kürzeste, aber das bedeutet nicht tatsächlich machen es die meisten wartbar.

Stattdessen würde ich so etwas wie dies vorschlagen:

$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
}

Daraus ergibt sich:

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

Ich denke, das nur ein bisschen mehr lesbar ist. Nicht nur das, ich denke, es ist auch einfacher zu debuggen und warten, denn das ist näher an, wie Sie es tun würden, wenn ein Mensch die gleiche Sache mit Stift und Papier, um zu versuchen sind. Brechen Sie die Zeichenfolge nach unten in Stücke, die Sie dann analysieren einfacher - haben den Computer genau das, was Sie tun würden. Wenn es darum geht, Änderungen zu machen, ich denke, das wird man besser. YMMV.

Versuchen Sie die ersten 3 (.*) ungreedy (.*?) machen

Wenn die Werte in Ihrem Semikolon getrennte Liste noch keine Semikolons selbst umfassen können, werden Sie die effizienteste und unkompliziert regulären Ausdruck bekommen einfach durch das Buchstabieren. Wenn bestimmte Werte nur sein kann, sagen wir, eine Reihe von Hex-Zeichen, das buchstabieren heraus. Lösungen eines faulen oder gierig Punkt verwenden, werden immer auf eine Menge nutzloser Rückzieher führen, wenn der Regex nicht die Zeichenkette entspricht.

(\d+:\d+)\ssay;([a-f0-9]+);(\d+);(\w+);([^;\r\n]+)

Sie können * nicht gierige machen durch ein Fragezeichen angehängt:

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

oder Sie können in jedem Teil mit Ausnahme der letzten, alles außer ein Semikolon entsprechen:

$line =~ /(\d+:\d+)\ssay;([^;]*);([^;]*);([^;]*);(.*)/
Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top