2010-08-26 16 views
14

Necesito una función como preg_replace pero en lugar de cadenas necesito que trabaje con archivos/contenido de archivos.Reemplazo de contenido de archivos en PHP

+0

Puede arrastrar el contenido de los archivos a una variable al recorrerlo usando fread y luego trabajar con preg_replace como lo haría con una cadena de texto? – Chris

+0

Sí, pero luego el contenido actualizado se debe escribir en los archivos de los que se tomó. –

+0

Entonces, ¿cuál es el problema para volver a escribir el contenido en el archivo? –

Respuesta

40

que puede hacer:

$file = 'filename'; 
file_put_contents($file,str_replace('find','replace',file_get_contents($file))); 
19

@ respuesta de codaddict es bastante sufficent para archivos pequeños (y sería cómo iba a ponerlo en práctica si el tamaño del archivo se encontraba bajo una MIB). Sin embargo, consumirá una tonelada de memoria y, como tal, debe tener cuidado al leer archivos de gran tamaño.

Si quieres una memoria Versión mucho más, podría utilizar stream filters ...

class ReplaceText_filter extends php_user_filter { 
    protected $search = ''; 
    protected $replace = ''; 

    public function filter($in, $out, &$consumed, $closing) { 
     while ($bucket = stream_bucket_make_writable($in)) { 
      $bucket->data = str_replace(
       $this->search, 
       $this->replace, 
       $bucket->data 
      ); 
      $consumed += $bucket->datalen; 
      stream_bucket_append($out, $bucket); 
     } 
     return PSFS_PASS_ON; 
    } 

    public function onCreate() { 
     if (strpos($this->filtername, '.') === false) return false; 
     list ($name, $arguments) = explode('.', $this->filtername, 2); 
     $replace = ''; 
     $search = $arguments; 
     if (strpos($arguments, '|') !== false) { 
      list ($search, $replace) = explode('|', $arguments, 2); 
     } 
     if (strpos($search, ',') !== false) { 
      $search = explode(',', $search); 
     } 
     if (strpos($replace, ',') !== false) { 
      $search = explode(',', $replace); 
     } 
     $this->search = $search; 
     $this->replace = $replace; 
    } 
} 
stream_filter_register('replacetext.*', 'ReplaceText_Filter'); 

Por lo tanto, a continuación, puede añadir un filtro de secuencia arbitraria. El nombre del filtro determina los argumentos:

$search = 'foo'; 
$replace = 'bar'; 
$name = 'replacetext.'.$search.'|'.$replace; 
stream_filter_append($stream, $name); 

o para matrices,

$search = array('foo', 'bar'); 
$replace = array('bar', 'baz'); 
$name = 'replacetext.'.implode(',', $search).'|'.implode(',', $replace); 
stream_filter_append($stream, $name); 

Obviamente este es un ejemplo muy simple (y no hace un montón de comprobación de errores), pero que le permite hacer algo como esto:

$f1 = fopen('mysourcefile', 'r'); 
$f2 = fopen('mytmpfile', 'w'); 
$search = array('foo', 'bar'); 
$replace = array('bar', 'baz'); 
$name = 'replacetext.'.implode(',', $search).'|'.implode(',', $replace); 
stream_filter_append($f1, $name); 
stream_copy_to_stream($f1, $f2); 
fclose($f1); 
fclose($f2); 
rename('mytmpfile', 'mysourcefile'); 

Y que mantendrá el uso de memoria muy baja al procesar archivos potencialmente enormes (GIB) o TiB ...

Ah, y la otra cosa interesante, es que puede editar en línea diferentes tipos de flujo. Lo que quiero decir con eso es que puede leer desde una secuencia HTTP, editar en línea y escribir en una secuencia de archivos. Es bastante potente (ya que puede encadenar estos filtros) ...

+0

El único problema con esta respuesta es cuando los términos de búsqueda se encuentran en diferentes sectores, especialmente cuando se trata de archivos de más de 8 KiB. – bit2shift

Cuestiones relacionadas