Search code examples
phpphp-7

Add text to specific line without removing the exist line in php


I'm trying to add only last name if first name is same

data.txt

Alice Sandy
Alice Nanami
James Watt
Alice Monica
Johann Gauss

to result.txt

Alice Sandy Nanami Monica
James Watt
Johann Gauss

I try with this code

$resultFile = "result.txt";
$search     = "Alice";
$lineNumber = false;
if ($handle = fopen($result, "r")) {
    $count = 0;
    while (($line = fgets($handle, 4096)) !== FALSE and !$lineNumber) {
        $count++;
        $lineNumber = (strpos($line, $search) !== FALSE) ? $count : $lineNumber;
        $isExist = (strpos($line, $search) !== FALSE) ? "yup" : "no";
    }
fclose($handle);
}
if($isExist=="yup"){
    $lines = file($resultFile);
    $lines[$lineNumber] = $lines[$lineNumber].' '.$lastName;
    file_put_contents($result, implode('', $lines));
}else{
    $fullName = $firstName.' '.$lastName;
    $fileOpen = fopen($result, "a");
    fwrite($fileOpen,$fullName);
    fclose($fileOpen);
    $addBreaker = "\n";
    $splResult = new SplFileObject($resultFile, 'a');
    $splResult->fwrite($addBreaker);
}

But it give error offset (I'm using PHP 7) and the result is untidy

Alice Sandy Nanami
 Monica
James Watt

Johan Gauss

Thanks for help


Solution

  • Use file() to collect the file contents as an array of lines. My snippet starts from there with $lines.

    Iterate the array and makes each line modifiable by reference. (&)

    Locate the first occurring needle match that not only exists in the line but matches the whole first word so that you don't get false-positive matching.

    Then declare the first match as a reference variable (=&) and continue iterating the array. Any subsequent matches will have the delimiting space and second word appended to the reference variable. Then immediate unset the line to be purged from the document.

    When done, re-implode the data and stuff the content into the result file.

    This is clean, readable, and only needs one loop.

    Code: (Demo)

    // $lines = file('result.txt', FILE_IGNORE_NEW_LINES);
    $lines = [
        'Alice Sandy',
        'Alice Nanami',
        'James Watt',
        'Alice Monica',
        'Johann Gauss',
        'Cooper Alice',
    ];
    
    $needle = 'Alice';
    foreach($lines as $index => &$line) {
        if ($needle === strstr($line, ' ', true)) { // check whole first word
            if (!isset($firstOccurrence)) {
                $firstOccurrence =& $line;
            } else {
                $firstOccurrence .= strstr($line, ' ');
                unset($lines[$index]);
            }
        }
    }
    var_export($lines);
    // file_put_contents('result.txt', implode(PHP_EOL, $lines));
    

    Output:

    array (
      0 => 'Alice Sandy Nanami Monica',
      2 => 'James Watt',
      4 => 'Johann Gauss',
      5 => 'Cooper Alice',
    )
    

    P.s if you want to know if any rows were changed you could check if the original array is === the new array after looping, or you could just use a boolean flag variable in the else condition.