How can I replace a particular line of text in file using php?
I don't know the line number. I want to replace a line containing a particular word.
How can I replace a particular line of text in file using php?
I don't know the line number. I want to replace a line containing a particular word.
One approach that you can use on smaller files that can fit into your memory twice:
$data = file('myfile'); // reads an array of lines
function replace_a_line($data) {
if (stristr($data, 'certain word')) {
return "replacement line!\n";
}
return $data;
}
$data = array_map('replace_a_line', $data);
file_put_contents('myfile', $data);
A quick note, PHP > 5.3.0 supports lambda functions so you can remove the named function declaration and shorten the map to:
$data = array_map(function($data) {
return stristr($data,'certain word') ? "replacement line\n" : $data;
}, $data);
You could theoretically make this a single (harder to follow) php statement:
file_put_contents('myfile', implode('',
array_map(function($data) {
return stristr($data,'certain word') ? "replacement line\n" : $data;
}, file('myfile'))
));
Another (less memory intensive) approach that you should use for larger files:
$reading = fopen('myfile', 'r');
$writing = fopen('myfile.tmp', 'w');
$replaced = false;
while (!feof($reading)) {
$line = fgets($reading);
if (stristr($line,'certain word')) {
$line = "replacement line!\n";
$replaced = true;
}
fputs($writing, $line);
}
fclose($reading); fclose($writing);
// might as well not overwrite the file if we didn't replace anything
if ($replaced)
{
rename('myfile.tmp', 'myfile');
} else {
unlink('myfile.tmp');
}
You have to overwrite the entire file.
So, for the relatively small file, read file into array, search for the word, replace found row, write all the rest into file.
For the big file the algorithm is slightly different, but quite the same in general.
Important part is file locking
that's why we prefer a database.
If you don't know the line, you will have to search over all lines.
Either iterate over the file line by line or read the file into memory all at once.
Then either find the word with a combination of strpos
and str_replace
or
use preg_replace
.
If you iterate, simply use strpos
and replace the line once it didn't return FALSE. Then save the file back to disk.
You can also use multi-line mode with regular expressions
preg_match_all('/word}/m', $textfile, $matches);
this is, of course, assuming it's a smaller document at the ready and loaded. Otherwise, the other answers are far more 'real-world' of a solution.
$filedata = file('filename');
$newdata = array();
$lookfor = 'replaceme';
$newtext = 'withme';
foreach ($filedata as $filerow) {
if (strstr($filerow, $lookfor) !== false)
$filerow = $newtext;
$newdata[] = $filerow;
}
Now $newdata
contains the file contents as an array (use implode()
if you don't want array) with the line containing "replaceme" replaced with "withme".
This is good if you are looking for a substring (ID) in a line and want to replace the old line with the new one.
Code:
$id = "123";
$new_line = "123,Programmer\r"; // We're not changing the ID, so ID 123 remains.
$contents = file_get_contents($dir);
$new_contents= "";
if( strpos($contents, $id) !== false) { // if file contains ID
$contents_array = preg_split("/\\r\\n|\\r|\\n/", $contents);
foreach ($contents_array as &$record) { // for each line
if (strpos($record, $id) !== false) { // if we have found the correct line
$new_contents .= $new_line; // change record to new record
}else{
$new_contents .= $record . "\r";
}
}
file_put_contents($dir, $new_contents); // save the records to the file
echo json_encode("Successfully updated record!");
}
else{
echo json_encode("failed - user ID ". $id ." doesn't exist!");
}
Example:
Old file:
ID,occupation
123,student
124,brick layer
Running the code will change file to:
New file:
ID,occupation
123,programmer
124,brick layer
You could turn the file into an array using the explode();
function, edit any item in the array, use the implode();
function to turn the array back into a string, then you can put the string back into the file using the file_put_contents();
function. This is shown in the following function :
function file_edit_contents($file_name, $line, $new_value){
$file = explode("\n", rtrim(file_get_contents($file_name)));
$file[$line] = $new_value;
$file = implode("\n", $file);
file_put_contents($file_name, $file);
}
Maybe this could help:
$data = file("data.php");
for($i = 0;$i<count($data);$i++){
echo "<form action='index.php' method='post'>";
echo "<input type='text' value='$data[$i]' name='id[]'><br>";
}
echo "<input type='submit' value='simpan'>";
echo "</form>";
if(isset($_POST['id'])){
file_put_contents('data.php',implode("\n",$_POST['id'])) ;
}
This function should replace a full line in a file:
function replace($line, $file) {
if ( file_get_contents($file) == $line ) {
file_put_contents($file, '');
} else if ( file($file)[0] == $line.PHP_EOL ) {
file_put_contents($file, str_replace($line.PHP_EOL, '', file_get_contents($file)));
} else {
file_put_contents($file, str_replace(PHP_EOL.$line, '', file_get_contents($file)));
}
}
The first if
statement (line 2) checks if the line to remove is the only line. It then empties the file. The second if
statement (line 4) checks if the line to remove is the first line in the file. If so, it then proceeds to remove that line by using str_replace($line.PHP_EOL, '', file_get_contents($file))
. PHP_EOL
is a new line, so this will remove the line contents and then the line break. Finally, the else
statement will only get called if the line to remove is not the only contents and it's not at the start of the file. It then uses the str_replace
, but this time with PHP_EOL.$line
and not $line.PHP_EOL
. That way, if the line is the very last line of the file, it will remove the line break before it and then delete the line.
Usage:
replace("message", "database.txt");
This removes a line with the contents message
from the file database.txt
if the line exists. If you wanted to shorten it, you could do something like this:
function replace($line,$file){if(file_get_contents($file)==$line){file_put_contents($file,'');}else if(file($file)[0]==$line.PHP_EOL){file_put_contents($file,str_replace($line.PHP_EOL,'', file_get_contents($file)));}else{file_put_contents($file,str_replace(PHP_EOL.$line,'',file_get_contents($file)));}}
I hope that answers your question :)
If you not going to lock the file while processing it, then
That said, it doesn't make sense to sacrifice accuracy for speed. This question states that a word must be matched in the line. For that reason, partial matches must be prevented -- regex offers word boundaries (\b
).
$filename = 'test.txt';
$needle = 'word';
$newText = preg_replace(
'/^.*\b' . $needle . '\b.*/mui',
'whole new line',
file_get_contents($filename)
1,
$count
);
if ($count) {
file_put_contents($filename, $newText);
}
The pattern:
/ #starting pattern delimiter
^ #match start of a line (see m flag)
.* #match zero or more of any non-newline character
\b #match zero-width position separating word character and non-word character
word #match literal string "word"
\b #match zero-width position separating word character and non-word character
.* #match zero or more of any non-newline character to end of line
/ #ending pattern delimiter
m #flag tells ^ character to match the start of any line in the text
u #flag tells regex engine to read text in multibyte modr
i #flag tells regex engine to match letters insensitively
If using case-insensitive searching but you need the actual matched word in the replacement string, write parentheses around the needle in the pattern, then use $1
in your replacement string.
You can do like this:
$file = file('data.txt');
$data = 'new text';
$some_index = 2;
foreach($file as $index => $line){
if($index == $some_index){
$file[$index] = $data . "\n";
}
}
$content = implode($file);
file_put_contents('data.txt', $content);
I've had similar task and gnarf's
answer helped a lot.
But better way to do this is JSON. If you have to change JSON file, you can use this code.
Code just gets existing JSON and applies that to the variable:
$base_data = json_decode(file_get_contents('data.json'), true);
$ret_data = json_encode($base_data , JSON_PRETTY_PRINT);
After this add/modify $ret_data
array as you like and put it back to file:
file_put_contents('data.json', $ret_data)
`
$base_data = json_decode(file_get_contents('data.json'), true);
if(!empty($_POST["update_data_file"])){
if(empty($_POST["update_key"]) || empty($_POST['update_value'])){
return_response(false, true, "Update Key or Update Value is missing");
}
if(!is_array($_POST["update_key"])){
return_response(false, false, "Update Key is not an array");
}
if(!is_array($_POST["update_value"])){
return_response(false, false, "Update Key is not an array");
}
$update_keys = $_POST['update_key'];
$update_values = $_POST['update_value'];
$key_length = count($update_keys);
$ret_data = $base_data; // $base_data is JSON from file that you want to update
for($i=0; $i<$key_length; $i++){
$ret_data[$update_keys[$i]] = $update_values[$i];
}
$ret_data = json_encode($ret_data, JSON_PRETTY_PRINT);
if(file_put_contents('data.json', $ret_data)){
return_response(true, false, "Data file updated");
}
return_response(false, false, "Error while updating data file");
}`
`
function return_response($success = true, $reload = false, $msg = ""){
echo json_encode
(
[
"success"=>$success,
"msg"=> $msg,
"reload"=> $reload
]
);
exit;
}`
JQuery part:
`
$("button").click(function(){
let inputs_array = $(this).data("inputs").split(",");
var input_value = "";
var post_input_keys = [];
var post_input_values = [];
for(var i = 0; i < inputs_array.length; i++){
input_value = $("#"+inputs_array[i]).val();
post_input_keys[i] = inputs_array[i];
post_input_values[i] = input_value;
}
send_ajax_data(post_input_keys, post_input_values);
});`
`
function send_ajax_data(update_key = [], update_value = []){
$.ajax({
type : "POST",
url : "path_to_php_file.php",
data : {
update_data_file: 1,
update_key: update_key,
update_value: update_value
},
dataType : 'json',
success : function(data) {
console.log(data.msg);
}
});
}`
HTML:
`
<form id="fill_details_form" class="form" action="" method="post">
<input type="hidden" name="update_data_file" value="1" />
<div class="row mt-3">
<div class="col-sm-3">
<div class="form-group">
<label for="form_name">Logo Width</label>
<input type="text" class="form-control" id="logo_width" name="logo_width" value="" />
<div class="help-block with-errors"></div>
</div>
</div>
<div class="col-sm-3">
<div class="form-group">
<label for="form_name">Logo Height</label>
<input type="text" class="form-control" id="logo_height" name="logo_height" value="" />
<div class="help-block with-errors"></div>
</div>
</div>
<div class="col-sm-3">
<label for="form_name"></label>
<div class="form-group">
<button
type="button"
id="update_logo_dims"
class="btn btn-primary"
data-inputs="logo_width,logo_height"
>
Update logo width and height
</button>
</div>
</div>
</div>
</form>
`
data.json example:
`
{
"logo_file_name": "favicon.png",
"logo_width": "153",
"logo_height": "36",
"logo_url": "https:\/\/google.com?logourl",
"website_url": "https:\/\/google.com",
"website_title": "WEbsite Title",
"favicon_file_name": "favicon.PNG",
}
`