使用PHP覆盖文件中的一行

18

如何最好地覆盖文件中的特定行? 我想要查找文件中的字符串“@parsethis”并用其他内容覆盖该行的其余部分。

7个回答

21

如果文件非常大(如日志文件等),并且您愿意为内存消耗而牺牲速度,您可以打开两个文件,并使用文件而不是系统内存来执行Jeremy Ruten提出的技巧。

$source='in.txt';
$target='out.txt';

// copy operation
$sh=fopen($source, 'r');
$th=fopen($target, 'w');
while (!feof($sh)) {
    $line=fgets($sh);
    if (strpos($line, '@parsethis')!==false) {
        $line='new line to be inserted' . PHP_EOL;
    }
    fwrite($th, $line);
}

fclose($sh);
fclose($th);

// delete old source file
unlink($source);
// rename target file to source file
rename($target, $source);

19
如果文件不太大,最好的方法可能是使用file()将文件读入到行数组中,搜索数组中的字符串并编辑该行,然后使用implode()将数组重新组合,并使用fwrite()将其写回文件。

2
这是我一直以来的做法。我很好奇是否有一种方法可以就地修改文件。 - Mark Biek
3
如果您在使用file()函数之后使用implode()函数,那么您可能希望将file_put_contents()函数用于同一行代码中以完成此操作。请注意,这不会更改原始意思。 - Frank N

6
您的主要问题在于新行可能与旧行长度不同。如果需要更改行的长度,则必须重写至少更改行后的整个文件,最简单的方法是创建一个新的修改后的文件,然后将其移动到原始文件上。这样,读者始终可以使用完整的文件。使用锁定以确保只有一个脚本在修改文件,并且由于您将替换文件,请在不同的文件上进行锁定。请查看flock()。
如果您确定新行与旧行长度相同,则可以以读/写模式打开文件(使用r+作为fopen()的第二个参数),并在每次调用fgets()读取一行之前调用ftell()保存行开始的位置。一旦找到要覆盖的行,就可以使用fseek()返回到行的开头,并使用fwrite()写入新数据。强制行始终具有相同的长度的一种方法是将其填充到最大可能长度。

1
这是一种使用PHP中的sed仅在文件中重写一行的解决方案。我的文件仅包含样式变量,并且格式为: $styleVarName: styleVarProperty;\n
为此,我首先将“:”添加到myStyleVarName的末尾,sed将替换该行的其余部分并添加分号以获得新属性。 请确保在myStyleVarProp中正确转义字符。
$command = "pathToShellScript folder1Name folder2Name myStyleVarName myStyleVarProp";
shell_exec($command);

/* shellScript */
#!/bin/bash
file=/var/www/vhosts/mydomain.com/$1/$2/scss/_variables.scss
str=$3"$4"
sed -i "s/^$3.*/$str;/" $file

0

或者如果你的文件不太大:

$sample = file_get_contents('sample');
$parsed =preg_replace('#@parsethis.*#', 'REPLACE TO END OF LINE', $sample);

你需要选择文件中不存在的分隔符“#”。


0
如果您想要完全用另一个文件的内容替换一个文件的内容,可以使用以下代码:
rename("./some_path/data.txt", "./some_path/data_backup.txt");
rename("./some_path/new_data.txt", "./some_path/data.txt");

所以在第一行中,您备份文件,在第二行中,您用新文件的内容替换文件。

据我所知,重命名返回一个布尔值。如果重命名成功,则为True,如果失败,则为false。因此,只有在第一步成功后才能运行第二步,以防止覆盖文件,除非已成功进行了备份。请查看:

https://www.php.net/manual/en/function.rename.php

希望对某些人有用。

祝好

Adrian


-1

我可能会像Jeremy建议的那样去做,但这里还有另一种解决方案。这个方案没有经过测试或使用,适用于*nix系统。

$cmd = "grep '@parsethis' " . $filename;
$output = system($cmd, $result);
$lines = explode("\n", $result);
// Read the entire file as a string
// Do a str_repalce for each item in $lines with ""

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接