PHP - найти строку в файле, а затем показать ее номер строки

У меня есть приложение, которому нужно открыть файл, затем найти в нем строку и напечатать номер строки, в которой найдена строка.

Например, файл example.txt содержит несколько хэшей:

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


Итак, я хочу, чтобы PHP выполнил поиск «1e9eea56686511e9052e6578b56ae018» и распечатал номер строки, в данном случае 4.

Обратите внимание, что в файле не будет нескольких хэшей.

Я нашел несколько кодов в Интернете, но ни один из них не работает.

Я попробовал это:

<?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"); 
} 
} 
?>

Он просто говорит, что строка найдена в строке 0.... Что неверно....

Окончательное приложение намного сложнее, чем это... После того, как оно находит номер строки, оно должно заменить строку чем-то другим и сохранить изменения в файле, а затем продолжить обработку....

Заранее спасибо :)


person xZero    schedule 04.11.2013    source источник
comment
А ваши возможные попытки?   -  person Hanky Panky    schedule 04.11.2013
comment
Я только что добавил свою последнюю попытку. Спасибо, что напомнили мне об этом.   -  person xZero    schedule 04.11.2013
comment
Причина, по которой ваша собственная попытка не работает, заключается в том, что strpos возвращает false, когда игла не найдена, что сделает ваше выражение if истинным. Вы должны написать !== false, чтобы такой оператор работал.   -  person Daniel Perván    schedule 04.11.2013
comment
@ Даниэль Перван - я только что попробовал, и да, теперь это работает. Спасибо!   -  person xZero    schedule 04.11.2013


Ответы (5)


Ультрабазовым решением может быть:

$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;

Версия для экономии памяти для больших файлов:

$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;
person evalarezo    schedule 04.11.2013
comment
Это не работает. Ничего не выводит... И да, пробовал echo $line_number; В любом случае, спасибо. - person xZero; 04.11.2013
comment
Теперь это работает как шарм. Выбрал ваш ответ как лучший, потому что мне нравится использовать file() вместо file_get_contents(); РЕДАКТИРОВАТЬ: версия для экономии памяти не работает. Вывод пустой. - person xZero; 04.11.2013
comment
Сейчас попробовал версию с экономией памяти, тоже отлично работает. Благодарю вас! - person xZero; 06.11.2013

Если вам нужно быстрое и универсальное решение, которое также работает для поиска номера строки многострочного текста в файле, используйте это:

$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");
}

К вашему сведению Работает только с PHP 5.3.0+.

person Alexander Yancharuk    schedule 11.06.2014

Если файл не очень большой, просто прочитайте файл в массив file, найдите слово preg_grep, получите индекс key для этой строки и добавьте 1, так как массив начинается с 0:

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

Я обнаружил, что это отлично работает и очень эффективно; Просто взорвите файл по каждой строке и найдите в массиве условия поиска следующим образом:

    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!';
    }

РЕДАКТИРОВАТЬ: просматривая другие ответы, я понимаю, что у Гильерме Соареса был аналогичный подход, но он использовал strpos, что в данном случае не работает. Поэтому я сделал несколько изменений с учетом его идеи:

    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!';
    }

Демонстрация в реальном времени: https://ideone.com/J4ftV3

person Crimin4L    schedule 24.02.2021

person    schedule
comment
Вы забыли добавить ; на return-ах, поэтому выдает ошибки. вернуть $num + 1; вернуть ложь; После исправления работает хорошо. Благодарю вас! - person xZero; 04.11.2013
comment
предупреждение: если файл большой, потребление памяти будет высоким, если вы используете file_get_contents() и explode(). - person Raptor; 04.11.2013
comment
Да, я это знал. Но пока он будет использоваться для файлов размером до 500кб. Я не уверен, как снизить потребление памяти.... - person xZero; 04.11.2013
comment
вместо return $num + 1; должно быть return $num; иначе будет строка после - person ; 04.08.2020