PHP: поиск в текстовом файле и вывод целой строки
Я пытаюсь создать скрипт на PHP, который будет искать внутри текстового файла и выводить целую строку, в которой найдено соответствие.
У меня есть текстовый файл (.txt) с названием "numorder.txt", и в этом файле содержатся несколько строк данных, новые строки добавляются каждые 5 минут (с помощью cron job). Данные имеют следующий вид:
2 aullah1
7 name
12 username
Как мне создать PHP-скрипт, который будет искать значение "aullah1" и затем выводить всю строку, в которой оно содержится? (В результате должно быть выведено "2 aullah1", без кавычек).
Если что-то объяснено неясно или вам нужно больше деталей, пожалуйста, дайте знать в комментариях.
5 ответ(ов)
Конечно! Вот перевод ответа на вопрос на StackOverflow:
Вот пример на PHP, который показывает, как вывести все строки, содержащие заданное слово в текстовом файле:
<?php
$file = 'somefile.txt'; // Указываем файл для чтения
$searchfor = 'name'; // Слово для поиска
// Эта строка предотвращает парсинг браузером как HTML
header('Content-Type: text/plain');
// Получаем содержимое файла, предполагая, что файл доступен для чтения (и существует)
$contents = file_get_contents($file);
// Экранируем специальные символы в запросе
$pattern = preg_quote($searchfor, '/');
// Завершаем регулярное выражение, чтобы совпадать с целой строкой
$pattern = "/^.*$pattern.*\$/m";
// Ищем совпадения и сохраняем их в $matches
if (preg_match_all($pattern, $contents, $matches)) {
echo "Найдены совпадения:\n";
echo implode("\n", $matches[0]); // Выводим все найденные строки
} else {
echo "Совпадений не найдено";
}
Этот код читает содержимое файла somefile.txt
, ищет все строки, содержащие слово name
, и выводит их. Если совпадений не найдётся, появляется сообщение об этом. Убедитесь, что файл существует и доступен для чтения, иначе код будет выдавать ошибку.
В вашем коде есть несколько моментов, которые стоит уточнить и исправить.
Открытие файла: Метод
fclose
используется для закрытия файлового дескриптора, но в вашем случае вы не открываете файл с помощьюfopen
. Используйтеfile_get_contents
, чтобы читать содержимое файла, но не следует в этом контексте вызыватьfclose
.Безопасность: Обратите внимание на безопасность. Вы используете значение из
$_GET
, что может привести к уязвимостям, таким как XSS или инъекции. Рекомендуется валидировать и экранировать входные данные.Неправильное закрытие файла: Ваша строка
fclose($file)
будет вызывать ошибку, поскольку переменная$file
— это не ресурс файла, а просто строка с именем файла.
Вот исправленный вариант вашего кода:
$searchfor = $_GET['keyword'] ?? ''; // Используем оператор ?? для установки значения по умолчанию
$file = 'users.txt';
$contents = file_get_contents($file);
if ($contents === false) {
echo "Ошибка при чтении файла.";
exit;
}
$pattern = preg_quote($searchfor, '/');
$pattern = "/^.*$pattern.*\$/m";
if (preg_match_all($pattern, $contents, $matches)) {
echo "Найденные совпадения:<br />";
echo implode("<br />", $matches[0]);
} else {
echo "Совпадений не найдено";
}
Объяснение изменений:
- Я добавил проверку на наличие или ошибку при чтении файла.
- Устранил вызов
fclose
, так как он здесь не нужен. - Добавил установку значения по умолчанию для
$searchfor
, чтобы избежать ошибок, еслиkeyword
не передан в GET-запросе.
Обязательно проверьте входные данные на безопасность и корректность!
В вашем случае, возможно, будет лучше использовать system("grep \"$QUERY\"")
, так как ваш скрипт не будет особенно эффективным в любом случае. В противном случае вы можете ознакомиться с документацией по функции file(), которая показывает, как проходить по строкам файла, и использовать strstr() для поиска совпадений.
Один из способов сделать это — использовать регулярные выражения для поиска строки, содержащей определенное слово. Вот пример кода:
$needle = "blah";
$content = file_get_contents('file.txt');
preg_match('~^(.*'.$needle.'.*)$~', $content, $line);
echo $line[1];
Тем не менее, более оптимальным решением будет чтение файла построчно с помощью fopen()
и fread()
и использование strpos()
для поиска искомого слова. Это поможет избежать проблем с производительностью при работе с большими файлами. Вот пример, как можно реализовать этот подход:
$needle = "blah";
$handle = fopen('file.txt', 'r');
if ($handle) {
while (($line = fgets($handle)) !== false) {
if (strpos($line, $needle) !== false) {
echo $line;
break; // прерываем, если нашли первую подходящую строку
}
}
fclose($handle);
} else {
// Обработка ошибок открытия файла
echo "Ошибка открытия файла.";
}
Такой подход обычно более эффективен, особенно для больших файлов, поскольку позволяет обрабатывать их по строкам и не загружать весь файл в память.
Ваш код немного модифицирован на основе упомянутого ответа и поддерживает несколько директорий и переменные ключевые слова через переменную GET. Если вам нужно реализовать это именно в этом формате, то вот пример, как можно это сделать:
if (isset($_GET["keyword"]) && isset($_GET["directory"])) {
$searchfor = $_GET["keyword"];
$directory = $_GET["directory"];
// Устанавливаем заголовок, чтобы браузер не интерпретировал как HTML.
header('Content-Type: text/plain');
// Получаем список файлов .php в указанной директории
foreach (glob($directory . '/*.php') as $file) {
// Проверяем, что файл читаем
if (is_readable($file)) {
// Получаем содержимое файла
$contents = file_get_contents($file);
// Экранируем специальные символы в запросе
$pattern = preg_quote($searchfor, '/');
// Завершаем регулярное выражение, соответствующее всей строке
$pattern = "/^.*$pattern.*\$/m";
// Ищем, и сохраняем все совпадения в $matches
if (preg_match_all($pattern, $contents, $matches)) {
echo "Найдены совпадения в файле: $file\n";
echo implode("\n", $matches[0]);
echo "\n\n";
}
}
}
}
Объяснение:
- Проверка параметров GET: Мы проверяем, установлены ли
keyword
иdirectory
. - Формирование пути: Мы используем переменную
$directory
для поиска файлов в заданной директории, что дает возможность осуществлять поиск в разных каталогах. - Чтение содержимого файлов: Убедимся, что файл читаем перед тем, как загружать его содержимое.
- Регулярные выражения: Формируем регулярное выражение таким образом, чтобы искать совпадения по всей строке.
- Вывод результатов: Если найдены совпадения, выводим сообщения с указанием файла и самими совпадениями.
Этот код позволит вам динамически искать в PHP-файлах с использованием переменных из GET-запроса, что делает его более универсальным и удобным для использования.
Как изменить цвет вывода echo в Linux
Функции startsWith() и endsWith() в PHP
Как читать большой файл построчно?
ReCaptcha 2.0 с использованием AJAX
Почему нельзя вызывать абстрактные функции из абстрактных классов в PHP?