Silja: Backslash entfernen

Hallo,
Ich möchte mit preg_replace einen Backslash vor ' bzw " entfernen.
Beispiel:  " aaaaa '
Nach langem Probieren ergibt sich mit nachfolgenden Zeilen

  
$mail_text = preg_replace('/\\\\\'/', "'", $mail_text);  
$mail_text = preg_replace('/\\\\\"/', '"', $mail_text);  

" aaaaa '

D.h. vor dem ' wird der Backslash entfernt, vor dem " nicht.
Was ist da noch falsch?
Und kann mir jemand erklären wie diese vielen \ zu erklären sind.
Gruß
Silja

  1. Tach!

    Ich möchte mit preg_replace einen Backslash vor ' bzw " entfernen.

    Warum nimmst du da nicht stripslashes()? Diese Backslashes kommen doch nur bei (immer noch aktivierten) Magic Quotes vor.

    $mail_text = preg_replace('/\\'/', "'", $mail_text);
    $mail_text = preg_replace('/\\"/', '"', $mail_text);

    Außerdem braucht man für solch simple Ersetzungen keine Funktionen für regulären Ausdrücke. str_replace() oder strtr() sind da kostengünstiger zu haben. Und sie haben auch nicht das Problem, dass man zwei Kontextwechsel beachten muss (und dafür eine Tonne Backslashes braucht), sondern nur einen.

    Und kann mir jemand erklären wie diese vielen \ zu erklären sind.

    Das PHP-Handbuch kann das. Kapitel zu den Strings, ''- und ""-Form, und die Seite zu preg_replace().

    dedlfix.

    1. was dedlfix oben geschrieben hat unterschreibe ich mit. Da gibt es einen Haufen Kontext-Wechsel, der kaum noch zu durchschauen ist. Auch das regex-Basteln will gelernt sein....

      Du hast:

      "

      Du kannst das in einen String packen mit

      A)
      '\"' - der erste Backslash maskiert den zweiten.

      ODER

      B)
      "\"" - der erste Backlslash maskiert den zweiten, der zweite das doppelte Anführungszeichen - das ja sonst den String begrenzen würde.

      Ich habe die regsearch mit '/\(")|\\(')/' gebaut weil die Quotas ja ausgegeben werden sollen. Die geklammerten Ausdrücke werden dann in $1 in $99 gespeichert.

      Nur für den Regex muss da nochmals maskiert werden.

      Wenn Du schon partout einen (teuren) regex verwenden willst, warum nicht in einem Schritt?:

      <?php  
      $str='foo\\\'bar\\"';  
      echo 'Kontrolle vor Ersetzen : '. $str , "    <br>\n";  
      $regsearch='/\\\(")|\\\\(\')/';  
      $str=preg_replace ($regsearch , '$1$2', $str);  
      echo 'Kontrolle nach Ersetzen: [/\\\\\(")|\\\\\\\\(\'/)] : ', $str, "    <br>\n";  
      ?>
      

      Ausgabe:

      Kontrolle vor Ersetzen : foo'bar"    <br>
      Kontrolle nach Ersetzen: [/\(")|\\('/)] : foo'bar"    <br>

      Das kann man noch interessanter haben (wenn man es richtig machen will) und auch noch jeweils noch doppelte Backlashs durch einfache ersetzen will... einfacher ist das aber wohl mit:

      <?php  
      $str='foo\\\'bar\\"baz\\\\potz\\\\\\\\blitz\\\\\\\\\\\\donnerwerter\\\\\\\\\\\\\\\\';  
      echo 'Kontrolle vor Ersetzen : '. $str , "    <br>\n";  
      $ar_search=array('\\\\', "\\'", '\\"');  
      $ar_replace=array('\\',"'", '"');  
      $str=str_replace($ar_search,$ar_replace,$str);  
      echo 'Kontrolle nach Ersetzen mit str_replace: ', $str, "    <br>\n";  
      ?>
      

      Ausgabe:

        
      Kontrolle vor Ersetzen : foo\'bar\"baz\\potz\\\\blitz\\\\\\donnerwerter\\\\\\\\    <br>  
      Kontrolle nach Ersetzen mit str_replace: foo'bar"baz\potz\\blitz\\\donnerwerter\\\\    <br>
      

      Jörg Reinholz

      1. Noch besser gehts mit stripslashes

        <?php  
        $str='foo\\\'bar\\"baz\\\\potz\\\\\\\\blitz\\\\\\\\\\\\donnerwerter\\\\\\\\\\\\\\\\';  
        echo 'Kontrolle : ', $str, "    <br>\n";  
        echo 'Kontrolle nach Ersetzen mit stripslashes: ', stripslashes ($str), "    <br>\n";  
        ?>
        

        Ausgaben:

        Kontrolle : foo\'bar\"baz\\potz\\\\blitz\\\\\\donnerwerter\\\\\\\\    <br>  
        Kontrolle nach Ersetzen mit stripslashes: foo'bar"baz\potz\\blitz\\\donnerwerter\\\\    <br>
        

        Jörg Reinholz

  2. Hi,

    $mail_text = preg_replace('/\\'/', "'", $mail_text);

    $mail_text = preg_replace('/\\"/', '"', $mail_text);

    
    >   
    > \" aaaaa '  
    >   
    > D.h. vor dem ' wird der Backslash entfernt, vor dem " nicht.  
    > Was ist da noch falsch?  
      
    dazu muss man etwas weiter ausholen, nämlich bis zur String-Notation in PHP.  
    In PHP kann man Stringkonstanten in 'einzelne' oder "doppelte" Anführungszeichen setzen. Das ist aber ein Bedeutungsunterschied: In double-quoted Strings werden viele Steuerzeichen und Escape-Sequenzen interpretiert, etwa \r, \n, \t, außerdem werden eingebettete Variablen aufgelöst. In single-quoted Strings passiert das alles nicht, die einzigen Sonderfälle, die hier beachtet werden, sind \' (sonst könnte ein einfaches Anführungszeichen nicht Teil des Strings sein) und \\, denn da der Backslash als Escape-Zeichen dient (wenn auch nur in einem Fall), muss er selbst auch escapet werden.  
      
    Also dröseln wir die beiden Strings mal auf:  
      
    '/\\\\\'/'   Ein forward slash /, ein Backslash \\, noch ein Backslash \\, ein Apostroph \',  
                 ein forward slash /  
                 Ergibt intern:  /\\'/  
    '/\\\\\"/'   Ein forward slash /, ein Backslash \\, noch ein Backslash \\, ein Backslash \,  
                 ein Anführungszeichen ", ein forward slash /  
                 Ergibt intern:  /\\\"/  
      
    Bemerkenswert ist eigentlich nur, dass in der Kombination \" im zweiten Beispiel der Backslash "wörtlich" genommen wird. Das liegt daran, dass die Kombination \" in single-quoted Strings nicht als Escape-Sequenz definiert ist (das Anführungszeichen kannst und musst du unmaskiert schreiben), und deshalb beide Zeichen "wörtlich" gelten.  
      
    
    > Und kann mir jemand erklären wie diese vielen \ zu erklären sind.  
      
    Ja. Es liegt an der zweifachen Verdopplung. Gehen wir rückwärts vor:  
    Damit die RegEx-Engine einen echten Backslash versteht und nicht eine mit dem Backslash eingeleitete Escape-Sequenz, muss dieser verdoppelt werden. Also müssen schon mal zwei Backslashes an die RegEx-Engine übergeben werden.  
    Um einen Backslash in einem PHP-String zu notieren, muss er verdoppelt werden. Um zwei Backslashes in einem PHP-String zu notieren, müssen beide verdoppelt werden.  
    Übrig bleibt der falsch verwendete fünfte Backslash im zweiten Beispiel.  
      
    So long,  
     Martin  
    
    -- 
    Zwischen Leber und Milz  
    passt immer noch'n Pils.  
    Selfcode: fo:) ch:{ rl:| br:< n4:( ie:| mo:| va:) de:] zu:) fl:{ ss:) ls:µ js:(
    
    1. Hi,
      danke für die ausführliche Erläuterung.

      Übrig bleibt der falsch verwendete fünfte Backslash im zweiten Beispiel.

      Allerdings  funktioniert das 2. Beipiel auch nicht, wenn ich einen Backslash weglasse.
      ($mail_text = preg_replace('/\\\\"/', '"', $mail_text);)
      Ich habe es deshalb jetzt mit str_replace versucht und zwar mit
      $mail_text = str_replace('\\"', '"', $mail_text);
      (\ wird "escaped" durch \ und " muss nicht "escaped" werden)
      Leider ohne Erfolg.
      Gruß
      Silja

      1. Tach!

        Allerdings  funktioniert das 2. Beipiel auch nicht, wenn ich einen Backslash weglasse.
        ($mail_text = preg_replace('/\\\\"/', '"', $mail_text);)
        Ich habe es deshalb jetzt mit str_replace versucht und zwar mit
        $mail_text = str_replace('\\"', '"', $mail_text);
        (\ wird "escaped" durch \ und " muss nicht "escaped" werden)
        Leider ohne Erfolg.

        Dann werden wohl deine Eingabedaten nicht zur Lösung passen. Ich kann keine Fehlfunktion nachvollziehen. Was sagt denn var_dump($eingabedaten_gekürzt_auf_relevante_länge);?

        '\"' ist gleichwertig zu '"'. \ ist ein maskierter . Da das " aber bereits als \ und " interpretiert wird, braucht es keinen extra maskierten .

        Und warum verwendest du nicht stripslashes()?

        dedlfix.