2017-08-15 2 views
2

ich folgend in einer MySQL-Datenbank am Speicherung:preg_match_all - Auszug Schlüssel/Wert von Vorlage

%URL% https://google.com 
%TEXT% Hello world! 
%LARGETEXT% Hello 
My name is ... 
I am from ... 

Mein Ziel ist es, die Saiten zu machen, die in% auf PHP-Array-Schlüssel eingewickelt werden und die Zeichenfolge sind neben die Werte.

Das Problem ist, dass meine Regex die mehrzeiligen Strings nicht extrahiert. Hier

ist der Code:

preg_match_all ("/%(\w+)%(.*)/", $msg, $matches); 

Es spielt Ausgabe:

[1]=> 
    array(3) { 
    [0]=> 
    string(5) "BASIC" 
    [1]=> 
    string(4) "TEXT" 
    [2]=> 
    string(9) "LARGETEXT" 
    } 
    [2]=> 
    array(3) { 
    [0]=> 
    string(18) " https://google.de" 
    [1]=> 
    string(13) " Hello world!" 
    [2]=> 
    string(6) " Hello" 
    } 

In der zweiten Reihe nur 'Hallo' gezeigt, statt:

Hello 
My name is ... 
I am from ... 

I tryed verschiedene regex aber ich komme immer zum selben ergebnis.

Antwort

2

Sie verwenden können

~%(\w+)%(.*?)(?=%\w+%|$)~s 

Siehe regex demo

Einzelheiten

  • % - ein Prozentzeichen
  • (\w+) - Gruppe 1: ein oder mehr Wort Zeichen
  • % - ein Prozentzeichen
  • (.*?) - Gruppe 2: alle 0+ Zeichen (beachten Sie, dass s Modifikator . Spiel Zeilenumbruch Zeichen, auch lassen wird) so wenig wie möglich, bis zum ersten Auftreten von ...
  • (?=%\w+%|$) - %, 1 + Wort Zeichen, % oder Ende der Zeichenfolge.

Ein identischer abgerollt Ausdruck (effizienteres) wird wie folgt aussehen

~%(\w+)%([^%]*(?:%(?!\w+%)[^%]*)*)~ 

(keine Notwendigkeit für die s Modifier). Siehe regex demo.

Die [^%]*(?:%(?!\w+%)[^%]*)* Matches alle 0+ Zeichen andere als %, und dann entspricht 0 oder mehr daraus folgende Vorkommen von % nicht mit 1+ Wort Zeichen gefolgt und % dann folgte mit irgendwelchen 0+ Zeichen anders als %.

Wenn Sie Ihre Eingaben immer am Anfang der verschiedenen Linien erscheinen Sie

~^%(\w+)%(.*?)(?=^%\w+%|\z)~sm 

Sehen Sie diese regex demo

Einzelheiten

  • ^ verwenden - entspricht dem Beginn eines Linie (aufgrund m modifier) ​​
  • %(\w+)% - % übereinstimmt, dann entspricht, und erfasst in Gruppe 1 eine oder mehrere Wort Zeichen, dann entspricht %
  • (.*?) - Spiele und erfasst in Gruppe 2 keine 0+ Zeichen so wenig wie möglich , bis zum ersten Auftreten von ...
  • (?=^%\w+%|\z) - Anfang einer Zeile, %, 1+ Wort Zeichen, % ODER zum Ende der Zeichenkette (\z könnte mit \Z hier, da nur der String-Ende Position ersetzt ist genug).

abgerollt Version:

~^%(\w+)%(.*(?:\R(?!%\w+%).*)*)~m 

Siehe another demo. Der (.*(?:\R(?!%\w+%).*)*) Teil entspricht der folgende in Gruppe 2:

  • .* - der Rest der Linie nach %, 1+ Wort Zeichen, % Teilzeichenfolge
  • (?:\R(?!%\w+%).*)* - Streichhölzer 0+ aufeinanderfolgenden Vorkommen von:
    • \R(?!%\w+%) - eine Zeilenumbruchsequenz (\R), die keine %, 1+ Wortzeichen und eine % danach hat und dann ...
    • .* - alle 0+ Zeichen außer Zeilenumbruchzeichen, so viele wie möglich, bis zum Ende der Zeile.
+0

Thank (entfernen Sie die trim, wenn Sie tatsächlich, obwohl die Zeilenumbrüche behalten wollen .. ich Sie nicht nur angenommen hat) Sie eine Menge. Ich werde Ihre Antwort so bald wie möglich als akzeptiert markieren. Das löst mein Problem. – user2933212

+0

Die zwei Muster sind falsch. Was passiert, wenn Sie eine URL mit Sonderzeichen durch hexadezimale Repräsentationen ersetzen, wie zum Beispiel: http: //domain.tld/fo%20%20lder/index.php? Path = http% 3A% 2F% 2Fotherdomain.tld'? Anstatt "%" zu verwenden, sollten Sie den Zeilenumbruch verwenden. –

+0

@CasimiretHippolyte: Sie können nicht sagen, dass die Muster * falsch * sind, ich schlug das Muster basierend auf dem ursprünglichen Muster vor, das * sich nicht auf die Zeilenumbrüche verlassen hat. Es ist einfach, dem ersten Regex Anker und einen MULTILINE-Modifikator hinzuzufügen, um es zu fixieren, und dann kann es leicht abgerollt werden. –

1

ein regex freien Ansatz:

$str=explode('%',$str); 
$arr=[]; 
for($i=1;$i<count($str);$i+=2){ 
    $arr[$str[$i]]=trim($str[$i+1]); 
} 
var_dump($arr); 

seems to work fine.