Мне нужна функция, аналогичная preg_replace, но вместо строк мне нужно, чтобы она работала с файлами / файловым содержимым.
Ты можешь сделать:
$file = 'filename'; file_put_contents($file,str_replace('find','replace',file_get_contents($file)));
Ответ @ codaddict довольно уместен для небольших файлов (и я бы это сделал, если размер файла находился под MiB). Однако он съедает тонну памяти, и поэтому вы должны быть осторожны при чтении больших файлов.
Если вы хотите гораздо более дружественную к памяти версию, вы можете использовать фильтры потока …
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');
Итак, вы можете добавить произвольный фильтр потока. Имя фильтра определяет аргументы:
$search = 'foo'; $replace = 'bar'; $name = 'replacetext.'.$search.'|'.$replace; stream_filter_append($stream, $name);
или для массивов,
$search = array('foo', 'bar'); $replace = array('bar', 'baz'); $name = 'replacetext.'.implode(',', $search).'|'.implode(',', $replace); stream_filter_append($stream, $name);
Очевидно, что это очень простой пример (и он не выполняет много проверок ошибок), но он позволяет вам сделать что-то вроде этого:
$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');
И это будет очень мало использовать память при обработке огромных (GiB или TiB) файлов …
О, и другая крутая вещь, может ли она встроить редактирование различных типов потоков. Я имею в виду, что вы можете читать из потока HTTP, редактировать inline и записывать в поток файлов. Это довольно мощный (так как вы можете связать эти фильтры) …