用 PHP 覆盖文件中的行
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/235604/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Overwrite Line in File with PHP
提问by Wilco
What is the best way to overwrite a specific line in a file? I basically want to search a file for the string '@parsethis' and overwrite the rest of that line with something else.
覆盖文件中特定行的最佳方法是什么?我基本上想在一个文件中搜索字符串 '@parsethis' 并用其他内容覆盖该行的其余部分。
回答by Stefan Gehrig
If the file is really big (log files or something like this) and you are willing to sacrifice speed for memory consumption you could open two files and essentially do the trick Jeremy Rutenproposed by using files instead of system memory.
如果文件真的很大(日志文件或类似的东西),并且您愿意牺牲内存消耗的速度,您可以打开两个文件,并基本上通过使用文件而不是系统内存来执行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);
回答by Jeremy Ruten
If the file isn't too big, the best way would probably be to read the file into an array of lines with file(), search through the array of lines for your string and edit that line, then implode()the array back together and fwrite()it back to the file.
如果文件不是太大,最好的方法可能是使用file()将文件读入一个行数组,在行数组中搜索您的字符串并编辑该行,然后implode()返回数组和fwrite()一起返回到文件中。
回答by Andru Luvisi
Your main problem is the fact that the new line may not be the same length as the old line. If you need to change the length of the line, there is no way out of rewriting at least all of the file after the changed line. The easiest way is to create a new, modified file and then move it over the original. This way there is a complete file available at all times for readers. Use locking to make sure that only one script is modifying the file at once, and since you are going to replace the file, do the locking on a different file. Check out flock().
您的主要问题是新行的长度可能与旧行的长度不同。如果您需要更改行的长度,那么至少在更改的行之后重写所有文件是没有办法的。最简单的方法是创建一个新的、修改过的文件,然后将它移到原始文件上。这样一来,读者就可以随时获得完整的文件。使用锁定来确保一次只有一个脚本在修改文件,并且由于您要替换文件,因此请对不同的文件进行锁定。退房flock()。
If you are certain that the new line will be the same length as the old line, you can open the file in read/write mode (use r+as the second argument to fopen()) and call ftell()to save the position the line starts at each time before you call fgets()to read a line. Once you find the line that you want to overwrite, you can use fseek()to go back to the beginning of the line and fwrite()the new data. One way to force the line to always be the same length is to space pad it out to the maximum possible length.
如果您确定新行与旧行的长度相同,您可以以读/写模式打开文件(r+用作 的第二个参数fopen())并调用ftell()以保存每次在您之前的行开始的位置调用fgets()读取一行。找到要覆盖的行后,您可以使用fseek()返回到行首和fwrite()新数据。强制线条始终保持相同长度的一种方法是将其间隔填充到最大可能长度。
回答by deusoz
This is a solution that works for rewriting only one line of a file in place with sed from PHP. My file contains only style vars and is formatted:
$styleVarName: styleVarProperty;\n
For this I first add the ":" to the ends of myStyleVarName, and sed replaces the rest of that line with the new property and adds a semicolon.
Make sure characters are properly escaped in myStyleVarProp.
这是一种解决方案,仅适用于使用 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///scss/_variables.scss
str=""
sed -i "s/^.*/$str;/" $file
回答by Adrian J G
If you want to completely replace the contents of one file with the contents of another file you can use this:
如果你想用另一个文件的内容完全替换一个文件的内容,你可以使用这个:
rename("./some_path/data.txt", "./some_path/data_backup.txt");
rename("./some_path/new_data.txt", "./some_path/data.txt");
So in the first line you backup the file and in the second line you replace the file with the contents of a new file.
所以在第一行备份文件,在第二行用新文件的内容替换文件。
As far as I can tell the rename returns a boolean. True if the rename is successful and false if it fails. One could, therefore, only run the second step if the first step is successful to prevent overwriting the file unless a backup has been made successfully. Check out:
据我所知,重命名返回一个布尔值。如果重命名成功则为真,如果失败则为假。因此,只有在第一步成功时才能运行第二步,以防止覆盖文件,除非已成功进行备份。查看:
https://www.php.net/manual/en/function.rename.php
https://www.php.net/manual/en/function.rename.php
Hope that is useful to someone.
希望这对某人有用。
Cheers
干杯
Adrian
阿德里安
回答by Ken
or if your file isn't too big:
或者如果您的文件不是太大:
$sample = file_get_contents('sample');
$parsed =preg_replace('#@parsethis.*#', 'REPLACE TO END OF LINE', $sample);
You'll have to choose delimiters '#' that aren't present in the file though.
不过,您必须选择文件中不存在的分隔符“#”。
回答by Gaurav
I'd most likely do what Jeremy suggested, but just for an alternate way to do it here is another solution. This has not been tested or used and is for *nix systems.
我很可能会按照 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 ""

