27

I need a function just like preg_replace but instead of strings I need it to work with files / file content.

5
  • You could pull file contents into a variable by looping over it using fread and then work with preg_replace as you would with a string of text ? Commented Aug 26, 2010 at 12:25
  • Yes but then the updated content should be written into the files it was taken from. Commented Aug 26, 2010 at 12:27
  • So what is the problem to write the content back to the file? Commented Aug 26, 2010 at 12:28
  • 2
    You could use the Unix utility sed. Commented Aug 26, 2010 at 12:28
  • PHP supports binary data in strings. Note there is a comment in the manual that the preg fns don't like strings greater than ~100k. However it probably will have problems with null chars in the source string - so read the file in chunks of up to (say) 10k, delimited by nulls, strip any trailing null (and keep it for later), apply the preg to each chunk and write it out again adding the null back if you removed one. Commented Aug 26, 2010 at 12:47

3 Answers 3

72

You can do:

$file = 'filename';
file_put_contents($file,str_replace('find','replace',file_get_contents($file)));
Sign up to request clarification or add additional context in comments.

Comments

26

@codaddict's answer is quite sufficent for small files (and would be how I would implement it if the size of the file was under a MiB). However it will eat up a ton of memory, and as such you should be careful when reading large files.

If you want a much more memory friendly version, you could use 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');

So, then you can append an arbitrary stream filter. The filter's name determines the arguments:

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

or for arrays,

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

Obviously this is a really simple example (and doesn't do a lot of error checking), but it allows you to do something like this:

$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');

And that will keep memory usage very low while processing potentially huge (GiB or TiB) files...

Oh, and the other cool thing, is it can inline edit differing stream types. What I mean by that is that you can read from a HTTP stream, edit inline, and write to a file stream. It's quite powerful (as you can chain these filters)...

1 Comment

The only problem with this answer is when the search terms are located across buckets, especially when dealing with files larger than 8 KiB.
0
<?php

$pattern = "/created/";
$replacement = "XXXXX";
$file_name = "regex.txt";
$getting_file_contents = file_get_contents($file_name);

echo("Original file contents : " . "<br><br>");
var_dump($getting_file_contents);
echo("<br><br><br>");

if ($getting_file_contents == true) {
  echo($file_name . " had been read succesfully" . "<br><br><br>");

  $replace_data_in_file = preg_replace($pattern, $replacement, $getting_file_contents);
  $writing_replaced_data = file_put_contents($file_name, $replace_data_in_file);
  echo("New file contents : " . "<br><br>");
  var_dump($replace_data_in_file);
  echo("<br><br>");

  if ($writing_replaced_data == true) {
    echo("Data in the file changed");
  }
  else {
    exit("Cannot change data in the file");
  }
}
else {
  exit("Unable to get file contents!");
}

?>

2 Comments

Can you add some explanation to this code? else it would be classified as a low quality answer
its basic php functions , you can just get the explanation from php.net/docs.php

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.