16

I have an application which needs to open the file, then find string in it, and print a line number where is string found.

For example, file example.txt contains few hashes:

APLF2J51 1a79a4d60de6718e8e5b326e338ae533
EEQJE2YX 66b375b08fc869632935c9e6a9c7f8da O87IGF8R
c458fb5edb84c54f4dc42804622aa0c5 APLF2J51
B7TSW1ZE 1e9eea56686511e9052e6578b56ae018
EEQJE2YX affb23b07576b88d1e9fea50719fb3b7


So, I want to PHP search for "1e9eea56686511e9052e6578b56ae018" and print out its line number, in this case 4.

Please note that there are will not be multiple hashes in file.

I found a few codes over Internet, but none seem to work.

I tried this one:

<?PHP
$string = "1e9eea56686511e9052e6578b56ae018"; 
$data   = file_get_contents("example.txt"); 
$data   = explode("\n", $data); 
for ($line = 0; $line < count($data); $line++) { 
if (strpos($data[$line], $string) >= 0) { 
die("String $string found at line number: $line"); 
} 
} 
?>

It just says that string is found at line 0.... Which is not correct....

Final application is much more complex than that... After it founds line number, it should replace string which something else, and save changes to file, then goes further processing....

Thanks in advance :)

4
  • 2
    And your possible attempts? Commented Nov 4, 2013 at 2:07
  • 1
    I just added my last attempt. Thanks for reminding me that. Commented Nov 4, 2013 at 2:17
  • 3
    The reason why your own attempt doesn't work is because strpos returns false when the needle isn't found which will make your if-statement evaluate as true. You must write !== false to make such statement work. Commented Nov 4, 2013 at 2:19
  • @Daniel Perván - I just tried it, and yep, it works now. Thanks! Commented Nov 4, 2013 at 2:33

6 Answers 6

18

An ultra-basic solution could be:

$search      = "1e9eea56686511e9052e6578b56ae018";
$lines       = file('example.txt');
$line_number = false;

while (list($key, $line) = each($lines) and !$line_number) {
   $line_number = (strpos($line, $search) !== FALSE) ? $key + 1 : $line_number;
}

echo $line_number;

A memory-saver version, for larger files:

$search      = "1e9eea56686511e9052e6578b56ae018";
$line_number = false;

if ($handle = fopen("example.txt", "r")) {
   $count = 0;
   while (($line = fgets($handle, 4096)) !== FALSE and !$line_number) {
      $count++;
      $line_number = (strpos($line, $search) !== FALSE) ? $count : $line_number;
   }
   fclose($handle);
}

echo $line_number;
Sign up to request clarification or add additional context in comments.

3 Comments

It doesn't work. It doesn't output nothing... And yes, I tried echo $line_number; Anyway, thanks.
Now it works like charm. Chosed your answer as best because I like usage of file() instead of file_get_contents(); EDIT: Memory saver version doesn't work. Output is blank.
Now I tried memory-saver version, and it also works perfectly. Thank you!
2
function get_line_from_hashes($file, $find){
    $file_content = file_get_contents($file);
    $lines = explode("\n", $file_content);

    foreach($lines as $num => $line){
        $pos = strpos($line, $find);
        if($pos !== false)
            return $num + 1
    }
    return false
}

get_line_from_hashes("arquivo.txt", "asdsadas2e3xe3ceQ@E"); //return some number or false case not found.

4 Comments

You forgot to add ; on return-s, so it throws errors. return $num + 1; return false; After correction it works well. Thank you!
warning: if the file is huge, memory consumption will be high if you use file_get_contents() and explode().
Yeah, I known that. But for now it will be used for files up to 500kb in size. I'm not sure how to lower memory consumption....
instead of return $num + 1; it needs to be return $num; or it gets the line after
2

If you need fast and universal solution that working also for finding line number of multiline text in file, use this:

$file_content = file_get_contents('example.txt');

$content_before_string = strstr($file_content, $string, true);

if (false !== $content_before_string) {
    $line = count(explode(PHP_EOL, $content_before_string));
    die("String $string found at line number: $line");
}

FYI Works only with PHP 5.3.0+.

Comments

1

If the file is not extremely large then just read the file into an array file, search for the word preg_grep, get the index key for that line and add 1 since the array starts at 0:

$string = "1e9eea56686511e9052e6578b56ae018"; 
echo key(preg_grep("/$string/", file("example.txt"))) + 1;

Comments

0
$pattern = '/1e9eea56686511e9052e6578b56ae018/';
if (preg_match($pattern, $content, $matches, PREG_OFFSET_CAPTURE)) {
    //PREG_OFFSET_CAPTURE will add offset of the found string to the array of matches
    //now get a substring of the offset length and explode it by \n
    $lineNumber = count(explode("\n", substr($content, 0, $matches[0][1])));
}

Comments

0

I found this to work great and be very efficient; Simply explode the file by each line and search through the array for your search terms like so:

    function getLineNum($haystack, $needle){

        # Our Count
        $c = 1;

        # Turn our file contents/haystack into an array
        $hsarr = explode("\n", $haystack);
        
        # Iterate through each value in the array as $str
        foreach($hsarr as $str){

            # If the current line contains our needle/hash we are looking for it
            # returns the current count.
            if(strstr($str, $needle)) return $c;

            # If not, Keep adding one for every new line.
            $c++;
        }

        # If nothing is found
        if($c >= count($hsarr)) return 'No hash found!';
    }

EDIT: Looking through the other answers, I realize that Guilherme Soares had a similar approach but used strpos, which in this case doesnt work. So I made a few alterations with his idea in mind here:

    function getLineNum($haystack, $needle){
        $hsarr = explode(PHP_EOL, $haystack);
        foreach($hsarr as $num => $str) if(strstr($str, $needle)) return $num + 1;
        return 'No hash found!';
    }

Live Demo: https://ideone.com/J4ftV3

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.