覆盖文件中特定行的最佳方法是什么?我基本上想在文件中搜索字符串 '@parsethis' 并用其他内容覆盖该行的其余部分。
7 回答
如果文件真的很大(日志文件或类似的东西)并且您愿意牺牲速度来消耗内存,您可以打开两个文件并基本上通过使用文件而不是系统内存来完成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);
您的主要问题是新线的长度可能与旧线不同。如果您需要更改行的长度,则没有办法在更改的行之后至少重写所有文件。最简单的方法是创建一个新的、修改过的文件,然后将其移到原始文件上。这样就可以随时为读者提供完整的文件。使用锁定以确保一次只有一个脚本在修改文件,并且由于您要替换文件,因此对不同的文件进行锁定。退房flock()
。
如果您确定新行与旧行的长度相同,您可以在读/写模式下打开文件(r+
用作 的第二个参数fopen()
)并调用ftell()
以保存该行在您之前的每次开始的位置调用fgets()
读取一行。找到要覆盖的行后,您可以使用fseek()
返回到行的开头和fwrite()
新数据。强制线始终保持相同长度的一种方法是将其空间填充到最大可能长度。
这是一个解决方案,仅适用于使用 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
或者如果您的文件不是太大:
$sample = file_get_contents('sample');
$parsed =preg_replace('#@parsethis.*#', 'REPLACE TO END OF LINE', $sample);
您必须选择文件中不存在的分隔符“#”。
如果你想用另一个文件的内容完全替换一个文件的内容,你可以使用这个:
rename("./some_path/data.txt", "./some_path/data_backup.txt");
rename("./some_path/new_data.txt", "./some_path/data.txt");
因此,在第一行中备份文件,在第二行中将文件替换为新文件的内容。
据我所知,重命名返回一个布尔值。如果重命名成功则为真,如果重命名失败则为假。因此,只有在第一步成功时才能运行第二步,以防止覆盖文件,除非已成功进行备份。查看:
https://www.php.net/manual/en/function.rename.php
希望这对某人有用。
干杯
阿德里安
我很可能会按照 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 ""