如何使用php从文件中删除一行?

如何使用php从文件中删除一行?,php,file,awk,line,Php,File,Awk,Line,我有一个名为$dir的文件和一个名为$line的字符串,我知道这个字符串是该文件的完整行,但我不知道它的行号,我想从文件中删除它,我该怎么办 是否可以使用awk?逐行读取,然后将匹配的行以外的所有行写入另一个文件。然后替换原始文件。另一种方法是逐行读取文件,直到找到匹配项,然后将文件截断到该点,然后附加其余的行。这将只查看每一行,如果它不是您要删除的,则会将其推送到一个数组中,并将其写回文件 $contents = file_get_contents($dir); $contents = str

我有一个名为
$dir
的文件和一个名为
$line
的字符串,我知道这个字符串是该文件的完整行,但我不知道它的行号,我想从文件中删除它,我该怎么办


是否可以使用awk?

逐行读取,然后将匹配的行以外的所有行写入另一个文件。然后替换原始文件。

另一种方法是逐行读取文件,直到找到匹配项,然后将文件截断到该点,然后附加其余的行。

这将只查看每一行,如果它不是您要删除的,则会将其推送到一个数组中,并将其写回文件

$contents = file_get_contents($dir);
$contents = str_replace($line, '', $contents);
file_put_contents($dir, $contents);
像这样:

file_put_contents($filename, str_replace($line . "\r\n", "", file_get_contents($filename)));

若要在一行中查找子字符串(ID),并希望用新行替换旧行,这也很好

代码:

$contents = file_get_contents($dir);
$new_contents = "";
if (strpos($contents, $id) !== false) { // if file contains ID
    $contents_array = explode(PHP_EOL, $contents);
    foreach ($contents_array as &$record) {    // for each line
        if (strpos($record, $id) !== false) { // if we have found the correct line
            continue; // we've found the line to delete - so don't add it to the new contents.
        } else {
            $new_contents .= $record . "\r"; // not the correct line, so we keep it
        }
    }
    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!");
}
示例:

$contents = file_get_contents($dir);
$new_contents = "";
if (strpos($contents, $id) !== false) { // if file contains ID
    $contents_array = explode(PHP_EOL, $contents);
    foreach ($contents_array as &$record) {    // for each line
        if (strpos($record, $id) !== false) { // if we have found the correct line
            continue; // we've found the line to delete - so don't add it to the new contents.
        } else {
            $new_contents .= $record . "\r"; // not the correct line, so we keep it
        }
    }
    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!");
}
输入:“123,学生”

旧文件:

身份证、职业

123,学生

124、砖层

运行代码会将文件更改为:

新文件:

身份证、职业

124、砖层


我认为处理文件的最佳方法是将它们当作字符串:

/**
*删除给定文件中找到的第一行。
*
*@param string$line要搜索的行内容。
*@param string$filePath要编辑的文件的路径。
*@param bool$removeOnlyFirstMatch是否仅删除第一个匹配项
*整个比赛。
*@如果发现(并删除)任何匹配项,则返回bool。
*
*@throw\RuntimeException(如果文件为空)。
*无法更新文件时发生@throw\RuntimeException。
*/
函数removeLineFromFile(
字符串$行,
字符串$filePath,
bool$removeOnlyFirstMatch=true
):bool{
//您可以将其包装在try-catch块中
$file=new\SplFileObject($filePath,“r”);
//检查文件大小是否为零
$fileSize=$file->getSize();
如果($fileSize!==0){
//阅读整个文件
$fileContent=$file->fread($fileSize);
}否则{
//文件是空的
抛出new\RuntimeException(“文件“$filePath”为空”);
}
//免费文件资源
$file=null;
//将文件内容分成几行
$fileLineByLine=explode(PHP_EOL,$fileContent);
$found=false;
foreach($fileLineByLine作为$lineNumber=>$thisLine){
如果($thisLine==$line){
$found=true;
未设置($fileLineByLine[$lineNumber]);
如果($removeOnlyFirstMatch){
打破
}
}
}
//如果找不到行,我们也不需要更新文件
如果(!$found){
返回false;
}
//把线连在一起
$newFileContent=内爆(PHP_EOL,$fileLineByLine);
//最后,更新文件
$file=new\SplFileObject($filePath,“w”);
如果($file->fwrite($newFileContent)!==strlen($newFileContent)){
抛出new\RuntimeException(“无法更新文件“$filePath”);
}
返回true;
}
下面是所做工作的简要说明:获取整个文件内容,将内容拆分为行(即作为数组),找到匹配项并删除它们,将所有行连接在一起,然后将结果保存回文件(仅当发生任何更改时)

现在让我们使用它:

/$dir是您的文件名,如您所述
从文件中删除行($line,$dir);
注意事项:

$contents = file_get_contents($dir);
$new_contents = "";
if (strpos($contents, $id) !== false) { // if file contains ID
    $contents_array = explode(PHP_EOL, $contents);
    foreach ($contents_array as &$record) {    // for each line
        if (strpos($record, $id) !== false) { // if we have found the correct line
            continue; // we've found the line to delete - so don't add it to the new contents.
        } else {
            $new_contents .= $record . "\r"; // not the correct line, so we keep it
        }
    }
    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!");
}
  • 您可以使用
    fopen()
    系列函数而不是
    SplFileObject
    ,但我确实建议使用对象形式,因为它基于异常,更健壮,更高效(至少在这种情况下)

  • 可以安全地使用foreach对数组中的元素进行
    unset()
    迭代(有一条注释显示它可能导致意外的结果,但这是完全错误的:正如您在示例代码中看到的那样,
    $value
    被复制(即它不是引用),删除数组元素不会影响它)

  • $line
    不应包含像
    \n
    这样的新行字符,否则可能会执行大量冗余搜索

  • 不要使用

    $fileLineByLine[$lineNumber]=”;
    //甚至
    $fileLineByLine[$lineNumber]=null;
    
    而不是

    unset($fileLineByLine[$key]);
    
    原因是,第一种情况不会删除该行,它只是清除该行(并且会保留一个不需要的空行)


希望有帮助。

不用awk也能解决:

function remove_line($file, $remove) {
    $lines = file($file, FILE_IGNORE_NEW_LINES);
    foreach($lines as $key => $line) {
        if($line === $remove) unset($lines[$key]);
    }
    $data = implode(PHP_EOL, $lines);
    file_put_contents($file, $data);
}

将文本转换为数组,删除第一行并重新转换为文本

$line=explode("\r\n",$text);
unset($line[0]);
$text=implode("\r\n",$line);

你是怎么知道这些台词的?您刚刚截断了文件…ionno,将它们放入内存,然后截断..只要文件不太大。并不是说这是一个更好的解决方案。。但是应该会导致更少的磁盘写入。那么awk呢?可以在php中使用吗?为什么要麻烦呢。PHP本身就可以很好地处理它。这个文件中可能有数十万行,所以我想用最有效的方法来处理:)这是处理更大文件(大于RAM大小)时更有效的方法awk是一个外部程序,您需要使用exec或类似函数调用它。我尝试了在每行之间编写代码回音,这很好,直到使用file\u put\u contents函数,我不明白为什么它不起作用:S@ibrahim-你什么意思?没用?你能通过
文件获取所有内容吗。确切地告诉我哪个部分不起作用。“file\u put\u contents”不会将内容写入文件以完全删除该行:
$contents=str\u replace($line.\n“,”$contents)@Amir有些时候线路制动器的制造方式有所不同,我刚刚尝试了我的解决方案,它如预期般工作。无论如何,尝试一下
$contents=str\u replace($line.PHP\u EOL,,$contents)而不是SO询问awk。你的答案也许能解决问题,但试着解释一下你是如何解决的。@Michael,答案也是如此