phpscanfgreedy

%s in sscanf() doesn't stop matching at hardcoded pipe in pattern


So I have abunch of files with formatted information, so several files containing multiple lines in this format: id|visits|info|name

When I run the following code, $id and $visits get matched correctly, only $info and $name seem to have some kind of problem. $info contains everything after the second | delimiter. And $name is empty.

Am I missing something?

<?php
$dir = new DirectoryIterator('./logs/');
foreach ($dir as $file) {
   if (!$file->isDot()) {
       $filename = $file->getFilename();
       $currentfile = fopen("./logs/$filename","r");
       if ($currentfile) {
           while (($line = fgets($currentfile)) !== false) {
               $n = sscanf($line, "%d|%d|%s|%s", $id,$visits,$info,$name);
               print "$name was visited $visits times<br>";
           }
           fclose($currentfile);
       } else {
          print "Error: Couldn't open file.<br>";
       }
   }
}
?>

Solution

  • $dir = new DirectoryIterator('./logs/');
    foreach ($dir as $file) {
        if (!$file->isDot()) {
            $filename = $file->getFilename();
            $currentfile = fopen("./logs/{$filename}", "r");
            if ($currentfile) {
                while (($line = fgets($currentfile)) !== false) {
                    $n = sscanf($line, "%d|%d|%[^|]|%s", $id, $visits, $info, $name);
                    print "{$name} was visited {$visits} times<br>";
                }
                fclose($currentfile);
            } else {
                print "Error: Couldn't open file.<br>";
            }
        }
    }
    

    You need to replace %d|%d|%s|%s with %d|%d|%[^|]|%s which can also contain regular expression. %[^|] reads all the characters except |. Since you're looking for a string in third delimiter, it takes all of the characters comes in the way till the end leaving the following delimiters to have empty literal value. Because you're using | as a delimiter, therefore, you need to prevent | from reading into %s to continue onto following delimiters. Numbers can be read easily but not easy for string when you have certain delimiters because string is everything from Numbers to any characters including delimiters except space since that's a reserved delimiter.

    Here, you need to use regex to set certain conditions to match what you want and extract it to the variables.

    Hope it helps!