Ingrid: Code kürzen?

Hallo meine Lieben,

mit

  
$site_edit_start = '<!-- START MAIN //-->';  
$site_edit_end = '<!-- END MAIN //-->';  
  
$alt_pre = file($site_name);  
$go = 0;  
for($x=0;$x<count($alt_pre);$x++)  
{  
	if(trim($alt_pre[$x]) == $site_edit_start)  
	{  
	  $go = 1;  
	}  
  
	if(trim($alt_pre[$x]) == $site_edit_end)  
	{  
	 $go = 0;  
	}  
  
	if($go == 1 && trim($alt_pre[$x]) != $site_edit_start && trim($alt_pre[$x]) != $site_edit_end)  
	{  
	 echo trim(htmlentities(strip_tags($alt_pre[$x])));  
	}  
}  

extrahiere ich einen bestimmten Bereich in einer Datei zwischen <!-- START MAIN //--> und <!-- END MAIN //-->.

Das Ganze funktioniert super.

Aber hat evtl. jemand eine Idee wie es kürzer/schneller/einfacher geht?

Ganz lieben Dank,

Ingrid

  1. Hallo Ingrid,

    Aber hat evtl. jemand eine Idee wie es kürzer/schneller/einfacher geht?

    kürzer will ich nicht versprechen - aber IMO einfacher und leichter nachvollziehbar.

    Zunächst mal würde ich nicht file() zum Lesen des Dateiinhalts verwenden, sondern file_get_contents(). Dann habe ich den Dateiinhalt nämlich nicht mehr als Array aus Strings vorliegen, die ich einzeln durchgehen muss, sondern als *einen* String, den ich am Stück behandeln kann.

    Grobentwurf ohne Garantie:

    $startseq = '<!-- START MAIN //-->';  
    $endseq   = '<!-- END MAIN //-->';  
      
    $text = file_get_contents($filename);  
      
    $start = strpos($text, $startseq);  
    $end   = strpos($text, $endseq);  
      
    if ($start===false              // start sequence not found  
     || $end===false                // end sequence not found  
     || $end<$start)                // end sequence found before start sequence  
     { echo 'Section not found';  
     }  
    else  
     { $start += strlen($startseq);  
       echo htmlspecialchars(trim(substr($text, $start, $end-$start)));  
     }
    

    Beachte, dass ich außerdem nicht htmlentities() verwende, sondern htmlspecialchars(), weil ich nicht sämtliche nicht-ASCII-Zeichen zu Entity-Referenzen verst&uuml;mmeln m&ouml;chte, sondern nur die Zeichen maskieren will, bei denen das nötig ist.

    So long,
     Martin

    --
    Wer im Steinhaus sitzt, soll nicht mit Gläsern werfen.
    Selfcode: fo:) ch:{ rl:| br:< n4:( ie:| mo:| va:) de:] zu:) fl:{ ss:) ls:µ js:(
    1. @@Der Martin:

      nuqneH

      Hallo Ingrid,

      Ja? ;-)

      $start = strpos($text, $startseq);

      $end   = strpos($text, $endseq);

        
      Äh, nö. Zweimal mit String^WByteoperation über einen String gehen ist vielleicht auch nicht performanter als dies einmal mit einem regulären Ausdruck zu tun.  
        
      Und muss auch nicht sein: Nach `$endseq`{:.language-php} muss man ja nur hinter dem Vorkommen von `$startseq`{:.language-php} suchen (und das auch nur, wenn es wirklich vorkommt). `[link:http://www.php.net/manual/de/function.strpos.php@title=strpos()]`{:.language-php} kennt dazu einen optionalen dritten Parameter.  
        
      ~~~php
      $start = strpos($text, $startseq);  
        
      if ($start !== false)  
      {  
        $start += strlen($startseq);  
        $end = strpos($text, $endseq, $start);  
      }  
      else  
      {  
        $end = false;  
      }
      

      Damit kann man sich

      if ($start===false              // start sequence not found

      || $end===false                // end sequence not found
      || $end<$start)                // end sequence found before start sequence

        
      auch sparen:  
        
      ~~~php
      if ($end === false)  
      {  
        echo 'Section not found';  
      }  
      else  
      {  
        echo htmlspecialchars(trim(substr($text, $start, $end-$start)));  
      }
      

      Qapla'

      --
      „Talente finden Lösungen, Genies entdecken Probleme.“ (Hans Krailsheimer)
  2. Für Anfänger verständlich:
    Du ermittelst die strpos von <!-- START MAIN //--> und von <!-- END MAIN //-->
    Und dann substr( $string, $strpos_startmain, $strpos_endmain - $strpos_startmain )

    Oder etwas komplexer mit preg_match(); Da wüßte ich aber auf Anhieb nicht den code für. Mit regulären ausdrücken stehe ich auf kriegsfuß.

    Gruß
    Kriegführer
    T-Rex

    1. Oder etwas komplexer mit preg_match(); Da wüßte ich aber auf Anhieb nicht den code für. Mit regulären ausdrücken stehe ich auf kriegsfuß.

      Komplexer? Wohl eher einfacher. ;)
      Der Regex würde so aussehen: <!-- START MAIN //-->(.*)<!-- END MAIN //-->
      Wichtig: bei mehreren "<!-- END MAIN //-->" wird alles bis zum letzten gefunden!
      Zusammen mit Martins Hinweis kriegt man das geschmeidig in 3-4 Zeilen hin.

      1. Wohl eher einfacher. ;)

        Das sagst Du (-;

        Der Regex würde so aussehen: <!-- START MAIN //-->(.*)<!-- END MAIN //-->

        Wie würde das dann genau aussehen?

        Nur eine Zeile?!

        Verstehe ich leider nicht ...

        Liebe Grüsse

        1. Om nah hoo pez nyeetz, Ingrid !

          Der Regex würde so aussehen: <!-- START MAIN //-->(.*)<!-- END MAIN //-->

          Wie würde das dann genau aussehen?

          <!-- START MAIN //-->(.*)<!-- END MAIN //-->

          Nur eine Zeile?!

          Ja.

          Der Punkt findet jedes beliebige Zeichen, der * sagt, dass beliebig viele beliebige Zeichen gefunden werden wollen, die Klammern sorgen dafür, dass man den gefundenen Teilstring auch weiter verarbeiten kann.

          Matthias

          --
          Der Unterschied zwischen Java und JavaScript ist größer als der zwischen Hebe und Heberden-Arthrose.

          1. Der Regex würde so aussehen: <!-- START MAIN //-->(.*)<!-- END MAIN //-->

            Wie würde das dann genau aussehen?
            <!-- START MAIN //-->(.*)<!-- END MAIN //-->
            Nur eine Zeile?!
            Ja.

            Der Punkt findet jedes beliebige Zeichen, der * sagt, dass beliebig viele beliebige Zeichen gefunden werden wollen,

            Das ist so nicht ganz richtig. Das Sternchen sagt, dass beliebig viele des vor dem Sternchen stehenden Elements gefunden werden sollen, nicht von beliebigen Zeichen.

            Dir ist das sicher klar, aber für Anfänger wie Ingrid sollte dieser kleine, aber feine Unterschied schon deutlich dargestellt werden.

            Zum Beispiel findet a* nicht beliebig viele beliebige Zeichen nach einem a, sondern beliebig viele a. Erst zusammen mit dem . (ein (eines!) beliebiges Zeichen) vor dem Sternchen, also .*, entsteht das Muster "beliebig viele beliebige Zeichen".

            So sähe der gewünschte Code ungefähr aus:

            if (preg_match('|' . $site_edit_start . "(.*)" . $site_edit_end . '|', $alt_pre, $treffer)) {
               var_dump($treffer);
            }

            In $treffer[0] befindet sich der auf das gesamte Muster passende Text, in $treffer[1] der Teil, der innerhalb des ersten runden Klammerpaars steht (entsprechend in $treffer[2] der eines zweiten runden Klammerpaars usw.).

            1. Ich setzt noch einen drauf :D.
              Man muss auch auf den richtigen Zeichensatz achten.

              Erst gestern hab ich lange an einem Problem rumgeschraubt, da preg_match einfach nix zurück lieferte. Und wieso? Weil ich nach utf8 in einem iso String gesucht habe. Sowas passiert wenn man sich auf die Arbeit von Kollegen verlässt...

              Und deshalb nenne ich preg_match komplexer.

              Gruß
              sich selbst bestätigender
              T-Rex

              1. @@T-Rex:

                nuqneH

                Ich setzt noch einen drauf :D.

                Eher drunter.

                Man muss auch auf den richtigen Zeichensatz achten.
                […] Weil ich nach utf8 in einem iso String gesucht habe.

                Was bitte hat Zeichensatz mit UTF-8 zu tun?

                Qapla'

                --
                „Talente finden Lösungen, Genies entdecken Probleme.“ (Hans Krailsheimer)
                1. Was hat Klug mit scheißen zu tun?
                  Na gut du hast ja recht... wie immer :(

                  Gruß
                  Tiefstapler
                  T-Rex

                  1. @@T-Rex:

                    nuqneH

                    Was hat Klug mit scheißen zu tun?

                    Wer klug isst, der scheißt auch klug.

                    Qapla'

                    --
                    „Talente finden Lösungen, Genies entdecken Probleme.“ (Hans Krailsheimer)
              2. Ich setzt noch einen drauf :D.
                Man muss auch auf den richtigen Zeichensatz achten.

                Ich setzte auch noch einen drunter :-D

                Der u modifier (PCRE_UTF8) ist nötig, wenn das Suchmuster UTF-8 enthält, in der Regel dann, wenn man UTF-8 Zeichenketten verarbeitet, was hier ja nicht der Fall ist.

                Aber hat evtl. jemand eine Idee wie es kürzer/schneller/einfacher geht?

                Ja, mittels REGEX und der Annahme, dass dein gesuchter Brocken mehrfach vorkommt, z.b. so:

                  
                if(preg_match_all('~(?<=START MAIN //-->).*(?=<!-- END MAIN)~sU',file_get_contents($site_name),$out)) {  
                  var_dump($out);  
                } else {  
                  echo "FAIL";  
                }  
                
                

                Array $out[0] sollte dann die gesuchten Stücke enthalten...

                Du suchst alle irgendwelche Zeichen (Punkt) begrenzt durch ein START MAIN //--> und <!-- END MAIN.

                Modifier
                Der s Modifier bestimmt, dass der Quantifikator Punkt im Suchmuster auch auf Zeilenumbrüche zutrifft.
                Der U Modfier kehrt die Gier von Quantifikatoren um. Quantifier werden ungreedy, genau so gut ginge in dem Fall ein Fragezeichen nach dem Quantifikator Stern.

                Lookarounds
                (?<= leitet einen positiven Lookbehind ein. Du möchtest alle Zeichen, vor denen ein START MAIN //--> vorkommt.
                (?= leitet einen positiven Lookahead ein. Alle Zeichen, bis <!-- END MAIN

                Lookarounds, damit das Ausgabe-Array nicht mit unnötigen Stücken gefüllt wird. Es gibt natürlich viele Möglichkeiten, so ein triviales Problem mittels REGEX zu lösen.

                lG,
                Jonny 5

                1. @@Jonny 5:

                  nuqneH

                  Ich setzte auch noch einen drunter :-D

                  In der Tat.

                  wenn man UTF-8 Zeichenketten verarbeitet, was hier ja nicht der Fall ist.

                  Das kann auch gar nicht der Fall sein, denn es gibt keine UTF-8-Zeichen.

                  Qapla'

                  --
                  „Talente finden Lösungen, Genies entdecken Probleme.“ (Hans Krailsheimer)
                  1. In der Tat.

                    wenn man UTF-8 Zeichenketten verarbeitet, was hier ja nicht der Fall ist.

                    Das kann auch gar nicht der Fall sein, denn es gibt keine UTF-8-Zeichen.

                    Doch, sicher gibt es UTF-8 strings, sogar bei Wikipedia :-)

                2. Der s Modifier bestimmt, dass der Quantifikator Punkt im Suchmuster...

                  Meine Güte, ich meinte natürlich das Metazeichen Punkt :-)

                3. Hallo,

                  Der u modifier (PCRE_UTF8) ist nötig, wenn das Suchmuster UTF-8 enthält, in der Regel dann, wenn man UTF-8 Zeichenketten verarbeitet, was hier ja nicht der Fall ist.

                  woher willst du das wissen? Ingrid hat nichts über die verwendete Zeichencodierung gesagt, es könnte also durchaus auch UTF-8 sein.
                  Das ist aber andererseits auch wurscht, solange Suchmuster und durchsuchter Text in derselben Codierung vorliegen.

                  Ja, mittels REGEX

                  Ob RegExp einfacher ist als Stringoperationen, darf bezweifelt werden.

                  So long,
                   Martin

                  --
                  Schildkröten können mehr über den Weg berichten als Hasen.
                  Selfcode: fo:) ch:{ rl:| br:< n4:( ie:| mo:| va:) de:] zu:) fl:{ ss:) ls:µ js:(
                  1. Hallo,

                    Der u modifier (PCRE_UTF8) ist nötig, wenn das Suchmuster UTF-8 enthält, in der Regel dann, wenn man UTF-8 Zeichenketten verarbeitet, was hier ja nicht der Fall ist.

                    woher willst du das wissen? Ingrid hat nichts über die verwendete Zeichencodierung gesagt, es könnte also durchaus auch UTF-8 sein.

                    Ja, das weiss ich nicht, aber für das Suchmuster spielt es in diesem Fall keine Rolle.

                    Das ist aber andererseits auch wurscht, solange Suchmuster und durchsuchter Text in derselben Codierung vorliegen.

                    Nicht immer nötig, wie z.B. in diesem Fall.

                4. Hallo Jonny 5!

                  Habe es jetzt so gemacht:

                    
                  $site_edit_start = '<!-- START MAIN //-->';  
                  $site_edit_end = '<!-- END MAIN //-->';  
                    
                  if(preg_match_all('~(?<='.str_replace("<!-- ", "", $site_edit_start).').*(?='.str_replace(" //-->", "", $site_edit_end).')~sU',file_get_contents($site_name),$out))  
                  {  
                      for($x=2;$x<sizeof($out[0]);$x++)  
                      {  
                          echo htmlspecialchars(strip_tags($out[0][$x]));  
                      }  
                  }  
                  
                  

                  Danke!

                  Liebe Grüsse, Ingrid

                  1. Hallo nochmal,

                    $site_edit_start = '<!-- START MAIN //-->';
                    $site_edit_end = '<!-- END MAIN //-->';

                    Wäre das Ganze auch möglich, wenn $site_edit_start und $site_edit_end gleiche Werte haben?

                    Also z.B.
                    $site_edit_start = '<!-- INHALT //-->';
                    $site_edit_end = '<!-- INHALT //-->';

                    Danke und liebe Grüße, Ingrid

                    1. Hallo Ingrid,

                      $site_edit_start = '<!-- START MAIN //-->';
                      $site_edit_end = '<!-- END MAIN //-->';
                      if(preg_match_all('~(?<='.str_replace("<!-- ", "", $site_edit_start).').*(?='.str_replace(" > //-->", "", $site_edit_end).')~sU',file_get_contents($site_name),$out))
                      {

                      Warum das str_replace? Vielleicht hat dich mein Suchmuster verwirrt, hatte einen Teil deiner ursprünglichen Begrenzer, der mir unnötig schien weggelassen.

                        
                      if(preg_match_all('~(?<='.$site_edit_start.').*(?='.$site_edit_end.')~sU',file_get_contents($site_name),$out)) { ...  
                      
                      

                      for($x=2;$x<sizeof($out[0]);$x++)

                      Gehe es doch einfacher mit foreach durch:

                        
                        foreach($out[0] AS $v) {  
                          var_dump($v);  
                        }  
                      
                      

                      Wäre das Ganze auch möglich, wenn $site_edit_start und $site_edit_end gleiche Werte haben?

                      Möglich schon, nur würde das Ergebnis ev. von dem abweichen, was du erwartest.
                      Beispielsweise 1<!-- INHALT //-->2<!-- INHALT //-->3<!-- INHALT //-->4<!-- INHALT //-->
                      Das Suchmuster würde 2,3 und 4 liefern. Wenn es nur paarweise matchen soll, dann besser so, wie zuvor schon erwähnt:

                        
                      preg_match_all('~(?:<!-- INHALT //-->).*(?:<!-- INHALT //-->)~sU'  
                      
                      

                      Gäbe dann 2 und 4 zurück.

                      Wenn man ?: nach der öffnenden Klammer schreibt, geht der zutreffende Inhalt nicht in das Ergebnis-Array. Benötigst <!-- INHALT //--> ja nur als Begrenzer.

                      Viel Erfolg und lG,
                      Jonny 5

            2. Om nah hoo pez nyeetz, Korinthenkackerin!

              Dir ist das sicher klar, aber für Anfänger wie Ingrid …

              T-Rex ist kein Anfänger :-p

              Matthias

              --
              Der Unterschied zwischen Java und JavaScript ist größer als der zwischen schwer und Schwerin.