Warnung: file_put_contents(/home/www/web1/html/php_dev/test.txt) [function.file-put-contents]: failed to open stream: Permission denied in /home/www/web1/html/php_dev/sys/lib.activity.php (Zeile 58)
Effizienteres PHP search-replace [Archiv] - PHP-Scripte PHP-Tutorials PHP-Jobs und vieles mehr

- Ad -
php-resource




Archiv verlassen und diese Seite im Standarddesign anzeigen :
Effizienteres PHP search-replace


 
loebbeshop
27-06-2003, 12:17 
 
Hallo,

mich beschäftigt seit einigen Tagen folgendes Problem:

Ca. 500 html-Dateien zu je 20kB sollen einen neuen Namen bekommen. Da die Seiten untereinander verlinkt sind, sollen auch die internen Links umbenannt werden. Meine bisherige Lösung hier als Schnipsel:

$piold = Array mit den alten Datei/Linknamen
$pinew = Array mit den neuen Datei/Linknamen
$ext = Dateiendung z.B. ".htm"

function writePI($piold, $pinew, $ext) {
for ($i=0; $i<sizeof($piold); $i++) {
$isopen = @fopen($piold[$i].$ext, "r");
if($isopen) $isdata=@fread($isopen, filesize($piold[$i].$ext));
$isdata = str_replace($piold, $pinew, $isdata);
@fclose($isopen);
$isopen = @fopen($pinew[$i].$ext, "w");
if($isopen) @fwrite($isopen, $isdata);
@fclose($isopen);
}
}
Ich weiss nicht wie str_replace intern arbeitet. Wenn die 20kB Datei, die ca. 10 Links enthält 500mal durchsucht wird um das search_and_replace durchzuführen scheint mir das nicht optimal. Vor allem, da diese Prozedur für alle 500 Dateien durchgeführt werden muss.

Eine Idee wäre per regular Expression die Links in der Datei zu suchen und dann mit einem assoziativen Array direkt zu ersetzen:

Die alten Links lauten abXXXXX.htm oder ab-XXXXX.htm oder acXXXXX.htm oder ac-XXXXX.htm, wobei XXXX alles Zahlen sind (mindestens 3). Das array würde dann z.B. ac-12345.htm => neuername.htm usw. beinhalten.

Ist das machbar? Oder habt jemand einen anderen Vorschlag?

Gruß...Lothar

 
loebbeshop
27-06-2003, 21:57 
 
Weiss jemand ob str_replace($searcharray, $replacearray, $text) beim Suchen ein Hash verwendet oder brute force?

Die o.g. Routine kommt mir ziemlich zäh vor, will sagen das script führt bereits ab 50 Dateien zum Abbruch.

 
Titus
28-06-2003, 09:55 
 
Das hier wär einen Versuch wert:

// erst alle Dateien in ein Array laden
// alte und neue Namen in eigene Arrays:

$i=0;
Schleife {
$files_alt[$i] = implode('', file($name_alt));
$namen_alt[$i] = preg_quote($name_alt);
$namen_neu[$i] = $name_neu;
$i++;
}

// ersetzen
$files_neu = preg_replace($namen_alt, $namen_neu, $files_alt);

// neue Dateien schreiben; alte Dateien löschen
foreach($files_neu as $i=>$data)
{
$fp = fopen($namen_neu[$i], 'w');
fputs($fp, $data);
fclose($fp);
unlink($namen_alt[$i];
$i++;
}siehe preg_quote (http://www.php-resource.de/manual.php?p=function.preg-quote) und preg_replace (http://www.php-resource.de/manual.php?p=function.preg-replace).

Wenn´s auch vielleicht nicht alles in einer Schleife geht wg. RAM-Problemen, so dürfte ein preg_replace doch schneller sein als 500mal str_replace.

 
loebbeshop
28-06-2003, 13:08 
 
Das Einlesen in ein grosses Array ist insofern problematisch, als das Skript auf unterschiedlichen gehosteten Servern lauffähig sein soll, unabhängig von der Dateizahl.

Dennoch meinen Dank für die Idee. Ich bin erst seit 10 Tagen PHPler und lerne mit jedem Codeschnipsel dazu.

Ich frage mich nach wie vor, wie das str_replace wohl das Suchen/Ersetzen abarbeitet. Wenn der zu durchsuchende Text pro Suchbegriff je einmal durchlaufen wird (also z.B. 500 mal für die 500 möglichen Suchbegriffe), dann lohnt sich sicher eine eigene Routine.

Vielleicht könnte ich mit preg_split anhand der Suchwörter den Text in ein array zerlegen. Der Suchbegriff steht nun am Anfang eines jeden Arrayeintrags. Dann ersetze ich diesen mit dem neuen Wert aus einem Hash und füge per implode den Text wieder zusammen.´

So loope ich zwar durch das Directory aber nicht mehr 500mal durch jedes File.


Alle Zeitangaben in WEZ +2. Es ist jetzt 15:41 Uhr.