Ankündigung

Einklappen
Keine Ankündigung bisher.

RegExp: Negierte Back References?

Einklappen

Neue Werbung 2019

Einklappen
X
  • Filter
  • Zeit
  • Anzeigen
Alles löschen
neue Beiträge

  • BlackWolf
    hat ein Thema erstellt RegExp: Negierte Back References?.

    RegExp: Negierte Back References?

    Tja, mal wieder treiben mich reguläre Ausdrücke zum Wahnsinn.

    Ich will einen regulären Ausdrück für folgendes. Ich habe z.B. eine Zeile ähnlich einer Variablenzuweisung in PHP, sowas wie
    muh = "eek";
    Was ich jetzt möchte ist eek auslesen. Das an sich ist nicht so schwer. Problematisch wird es dann aber wenn folgendes dazu kommt:
    1) eek kann auch ein mehrzeiliger Text sein (newlines sind keine Begrenzungen)
    2) " können auch durch ' ersetzt werden
    3) Nach der Zeile können noch ähnliche Zeilen auftauchen, ich muss also aufpassen das nicht zuviel gematcht wird

    So ... ich hatte es jetzt probiert mit folgendem Regexp:
    /^[a-z0-9\._-]+ *= *("|\')[^\1]+\1 *;/ims

    Um euch das lesen etwas zu vereinfachen:
    ^[a-z0-9\._-]+: Am Anfang des Strings kommt der "Variablenname" der nur aus den angegeben zeichen bestehen darf
    Danach kommen beliebig viele Whitespaces
    Dann ein =
    Dann wieder beliebige Whitespaces
    Dann entweder ein " oder '
    Jetzt soll jedes beliebige Zeichen kommen außer " oder ', je nachdem was gematcht wurde
    Dann ein " oder ', je nachdem was gematcht wurde
    Wieder mal beliebig viele Whitespaces
    Schließlich ein ;

    So, das Problem: Diese "Back References", also das \1, funktionieren nicht in eckigen Klammern.

    Lange Rede kurzer Sinn: Gibt es dafür ein Workaround oder hat jemand evtl. sogar einen besseren Ansatz für mein Problem? Das Problem ist ganz einfach das ich verbieten muss das " oder ' (je nachdem was eben eingesetzt wird um die Zeichenkette zu begrenzen) in der Zeichenkette vorkommen, da ich sonst schwachsinnige Ergebnisse kriege.
    der U-Modifier ist leider auch keine Lösung, da ich später noch escaping einbauen will. Und bei U würde sowas wie
    muh = "ee\"k";
    nur bis vor das k gematcht werden.

    Naja: Ideen?

    Danke
    BlackWolf

  • nikosch
    antwortet
    Escapezeichen gehen über ODER und Wiederholung:

    *kram* irgendwo hatte ich das schon mal umgesetzt: muß ich nachliefern...

    [edit]
    Nur mal exemplarisch für die DblQuotes:
    Code:
    preg_match_all ('#\"((?:(?:\\\")|[^\\"]+)+)\"#U' , $test , $aElements);
    Mit escapten backslashes wirds wieder ein Stück komplizierter.

    Einen Kommentar schreiben:


  • dr.e.
    antwortet
    Das aber nur so am Rande ...
    Danke für den Hinweis, man lernt nie aus.

    Einen Kommentar schreiben:


  • nikosch
    antwortet
    PHP-Code:
    $test ="sdjklfhd = 'abcd\"';";

    preg_match('/^([a-z0-9\_\-\.]+)[ ]{0,}=[ ]{0,}([\"\'])(.+)\2;/iUms',$test,$matches);
    print_r($matches);

    $test ='sdjklfhd = "abcd\'sadsa";';

    preg_match('/^([a-z0-9\_\-\.]+)[ ]{0,}=[ ]{0,}([\"\'])(.+)\2;/iUms',$test,$matches);
    print_r($matches);
    /*
    Array
    (
        [0] => sdjklfhd = 'abcd"';
        [1] => sdjklfhd
        [2] => '
        [3] => abcd"
    )
    Array
    (
        [0] => sdjklfhd = "abcd'sadsa";
        [1] => sdjklfhd
        [2] => "
        [3] => abcd'sadsa
    )

    */ 
    Man kann sogar escapte Delimiter eibauen mit einem Oder Statement.

    Einen Kommentar schreiben:


  • BlackWolf
    antwortet
    Zitat von dr.e. Beitrag anzeigen
    Das Problem dabei ist das ODER. Es gibt demnach keine Zusage darüber, dass, falls beim ersten Versuch ein " verwendet wurde, dies auch beim zweiten Mal erfolgt. Man muss sich entweder entscheiden oder auf strpos() & substr() umsteigen. Regexps geben das in dieser Form nicht her.


    Gerne.
    Naja, geben sie in dem Sinne schon, nämlich eben über Back References. Aber Back References lassen sich eben nicht in Verbindung mit NOT verwenden, das ist das Problem. Sowas z.B. geht aber schon:
    ("|')(.+)\1
    das würde "muh" und 'muh' matchen, aber nicht "muh'
    Das aber nur so am Rande ...

    Aber werde dann wohl einfach festlegen das " verwendet werden müssen.

    Wenn ich das Topic aber schon grad offen hab nämlich noch ne kleine Frage: Hat jemand ne Idee wie ich ein escape zeichen einbaun kann? Im Klartext:
    "ha"llo"
    soll nicht gematcht werden aber
    "ha\"llo"
    eben schon.

    Ich hatte es versucht mit
    [^[^\\]"]+
    das wollte aber nicht.

    Einen Kommentar schreiben:


  • nikosch
    antwortet
    Hmm, na wozu brauchst Du denn Klassen:

    Code:
    preg_match('/^([a-z0-9\_\-\.]+)[ ]{0,}=[ ]{0,}([\"\'])(.+)\2;/iUms',$test,$matches);
    oder ähnlich (ungetestet) sollte mit ungreedy doch auch gehen.
    Zudem kannst Du auch beide Fälle als oder darstellen:
    Code:
    ...(?:\"([^\"]+)\"|\'([^\']+)\')...

    Einen Kommentar schreiben:


  • dr.e.
    antwortet
    Ich hätte es halt gerne habt das ich sowohl " als auch ' verwenden kann, aber das scheint nicht möglich zu sein.
    Das Problem dabei ist das ODER. Es gibt demnach keine Zusage darüber, dass, falls beim ersten Versuch ein " verwendet wurde, dies auch beim zweiten Mal erfolgt. Man muss sich entweder entscheiden oder auf strpos() & substr() umsteigen. Regexps geben das in dieser Form nicht her.

    Danke auf jeden Fall!
    Gerne.

    Einen Kommentar schreiben:


  • BlackWolf
    antwortet
    Zitat von dr.e. Beitrag anzeigen
    Hi,

    dann versuche nochmal statt "\1" ein "$1" zu schreiben. Bei mir tut folgender Code seinen Dienst:

    PHP-Code:
    $test 'fo9o="b
       a
       mein )=(/&%$/()=Itest
       r";'
    ;
    preg_match('/^([a-z0-9\_\-\.]+)[ ]{0,}=[ ]{0,}\"([^\"]+)\";/iUms',$test,$matches);
    echo 
    print_r($matches); 
    ne, $1 hatte ich auch schon probiert, tuts leider nich.
    Dein Code wäre mein Ausweich-Code gewesen, dann muss die rechte Seite vom Gleichheitszeichen halt in " eingeschlossen sein, ' sind dann tabu.
    Ich hätte es halt gerne habt das ich sowohl " als auch ' verwenden kann, aber das scheint nicht möglich zu sein.

    Danke auf jeden Fall!

    mfg

    Einen Kommentar schreiben:


  • dr.e.
    antwortet
    Hi,

    dann versuche nochmal statt "\1" ein "$1" zu schreiben. Bei mir tut folgender Code seinen Dienst:

    PHP-Code:
    $test 'fo9o="b
       a
       mein )=(/&%$/()=Itest
       r";'
    ;
    preg_match('/^([a-z0-9\_\-\.]+)[ ]{0,}=[ ]{0,}\"([^\"]+)\";/iUms',$test,$matches);
    echo 
    print_r($matches); 

    Einen Kommentar schreiben:


  • BlackWolf
    antwortet
    Zitat von dr.e. Beitrag anzeigen
    Du musst IMHO "\\1" schreiben, sonst wird der Backslash nicht erkannt...?
    Nein, weil das Backslash in dem Fall Teil der Syntax ist.
    Die Back-Reference funktioniert auch über \1, nur eben nicht in den eckigen Klammern, was aber eben auch das PHP-Manual sagt. Das gibt es nicht.

    Die Frage ist wie ich mein Problem gelöst kriege.

    Einen Kommentar schreiben:


  • dr.e.
    antwortet
    So, das Problem: Diese "Back References", also das \1, funktionieren nicht in eckigen Klammern.
    Du musst IMHO "\\1" schreiben, sonst wird der Backslash nicht erkannt...?

    Einen Kommentar schreiben:

Lädt...
X