【问题标题】:Overwrite Line in File with PHP用 PHP 覆盖文件中的行
【发布时间】:2010-09-19 03:13:08
【问题描述】:

覆盖文件中特定行的最佳方法是什么?我基本上想在文件中搜索字符串“@parsethis”并用其他内容覆盖该行的其余部分。

【问题讨论】:

    标签: php file-io fopen fwrite


    【解决方案1】:

    如果文件真的很大(日志文件或类似的文件)并且您愿意牺牲速度来消耗内存,您可以打开两个文件并基本上通过使用文件而不是系统内存来完成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);
    

    【讨论】:

      【解决方案2】:

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

      【讨论】:

      • 这就是我一直以来的做法。我很想知道是否有办法就地修改文件。
      • 如果你使用 file() for in,在 implode 之后你可能也希望 file_put_contents() 在一行中完成。
      【解决方案3】:

      您的主要问题是新行的长度可能与旧行不同。如果您需要更改行的长度,则没有办法在更改的行之后至少重写所有文件。最简单的方法是创建一个新的、修改过的文件,然后将其移到原始文件上。这样就可以随时为读者提供完整的文件。使用锁定来确保一次只有一个脚本在修改文件,并且由于您要替换文件,因此对不同的文件进行锁定。查看flock()

      如果您确定新行与旧行的长度相同,您可以以读/写模式打开文件(使用r+ 作为fopen() 的第二个参数)并调用ftell()在每次调用fgets() 读取一行之前保存行开始的位置。找到要覆盖的行后,您可以使用fseek() 回到行首并使用fwrite() 新数据。强制线条始终保持相同长度的一种方法是将空格填充到可能的最大长度。

      【讨论】:

        【解决方案4】:

        这是一种解决方案,仅适用于使用 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
        

        【讨论】:

          【解决方案5】:

          或者如果您的文件不是太大:

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

          您必须选择文件中不存在的分隔符“#”。

          【讨论】:

            【解决方案6】:

            如果你想用另一个文件的内容完全替换一个文件的内容,你可以使用这个:

            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

            希望对某人有用。

            干杯

            阿德里安

            【讨论】:

              【解决方案7】:

              我很可能会按照 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 ""
              

              【讨论】:

                猜你喜欢
                • 2015-05-24
                • 2013-05-20
                • 2013-05-11
                • 1970-01-01
                • 2022-01-25
                • 1970-01-01
                • 1970-01-01
                • 2015-04-21
                • 2015-03-05
                相关资源
                最近更新 更多