Strict Standards: Resource ID#33 used as offset, casting to integer (33) in /home/tvoyweb/domains/tvoyweb.ru/public_html/forums/include/fm.class.php on line 401

Strict Standards: Resource ID#35 used as offset, casting to integer (35) in /home/tvoyweb/domains/tvoyweb.ru/public_html/forums/include/fm.class.php on line 401

Strict Standards: Resource ID#36 used as offset, casting to integer (36) in /home/tvoyweb/domains/tvoyweb.ru/public_html/forums/include/fm.class.php on line 401
ТвойWeb :: Версия для печати :: Поиск по списку на PHP
ТвойWeb » WebMaster класс » PHP/Perl » Поиск по списку на PHP

Страниц (1): [1]
 

1. UFO - 08 Февраля, 2008 - 09:55:21 - перейти к сообщению
Привет! Улыбка
Возникла такая задача: реализовать поиск по списку, который записан по частям в файлы от a.dat до z.dat (26_латинских_букв.dat). В каждом файле приблизительно 8 тысяч строк. Но во всех файлах разное кол-во. На каждой строчке восьмисимвольная запись. Как организовать поиск части слова этих записей по каждому из списков? Допустим, пользователь вводит слово "yes", нажимает кнопку и скрипт ищет в каждом файле, на каждой строчке запись, которая содержит в себе слово "yes". Если найдено такое, то выводим его на экран. Было бы неплохо, если бы вывод выглядел приблизительно так:
Цитата:
Файл: a.dat
Найдено:
ayes
iyes
zyes
====
Файл: c.dat
Найдено:
ryes
====
и т.д.

Если в определенном файле ничего не найдено, то можно ничего и не выводить.
Итак, вопрос: как же правильнее и проще всего сделать такой поиск?
2. Furax - 08 Февраля, 2008 - 23:58:00 - перейти к сообщению
UFO
Я бы сделал через регулярные выражения. Т. е. введённая пользователем строка преобразуется в regexp и потом это выражение ищется по всему файлу. Что-то типа /\b.*yes.*\b/.

Хотя, если сервак под *nixами, можно воспользоваться системной функцией grep, насчёт синтаксиса которой я подсказать не могу. Короче, через командную строку.

Если же речь идёт о том, как получить имена всех нужных файлов - я бы сделал вот так:
CODE:
foreach (glob('files/?.dat') as $file) ...
3. UFO - 10 Февраля, 2008 - 14:30:25 - перейти к сообщению
Furax
Да, как вывести название файла - ясно, но все таки с поиском не все ясно.
Как сделать так, чтобы выражение искалось во всех 26 файлах? 26 раз писать переменную? И еще: можно по-точнее, функцию какого регулярного выражения надо использовать? preg_match_all? Было бы неплохо, если бы были хоть какие-нибудь наброски кода (извиняюсь за дерзость Улыбка ), т.к. я даже не знаю как реализовать наиболее просто.
4. Furax - 11 Февраля, 2008 - 01:22:37 - перейти к сообщению
UFO
В цикле просмотреть файлы и для каждого по очереди сделать поиск и в случае удачи вывести результат. Да, preg_match_all.

Код? Что-то типа этого:
CODE:
foreach (glob('db/?.dat') as $file)
{
$out=array();
if (preg_match_all($pattern, file_get_contents($file), $out)
{
print "$file:<br> " . implode('<br>', $out) . '<br>';
}
}
Где $pattern - это строка шаблона, сформированная на основе поискового запроса.
5. UFO - 20 Февраля, 2008 - 14:03:56 - перейти к сообщению
Все никак не могу разобратся, проблема с preg_match_all и с выводом результата поиска. Вопрос относительно 26 файлов решил упростить - проще сделать всю базу в одном файле и по ней искать. Решено - теперь файл один, но проблемы все равно остались.
На данный момент скрипт выглядит так:
CODE:
<center>Поиск<br>
<form action="<?php echo $_SERVER['PHP_SELF']; echo "?p=find"; ?>" method="POST" name="find">
<input type=text value="<? echo $slovo ?>" size="10" maxlength="4" name="slovo">.net<br>
<a href="index.php" onclick="document.find.submit(); return false">Проверить >>></a></form><br><br>
<?php
if (($act<>null) && ($slovo==null))
{
echo "Не был введен поисковый запрос</center>";
}
if (preg_match("#[^A-Za-z\-]#is",$slovo))
{
echo "Поисковый запрос содержит недопустимые символы или введен не правильно. Допустимые символы: <font color=red>a-z</font> (буквы латинского алфавита) и <font color=red>-</font> (дефис).</center>";
} else
if ($slovo<>null) {
if ((strlen($slovo)<2) or (strlen($slovo)>4)) {
echo "Поисковый запрос должен состоять как минимум из двух, и как максимум из четырех символов";
} else {
$out=array();
$fila = file("pages/db/a.dat");
$lina = count($fila);
for ($i = 0 ; $i < $lina; $i++)
{
if (preg_match_all("/\b.* $slovo .*\b/", $lina[$i], $out))
// Тут начинаются проблемы. Вроде как результат в $out...
echo $lina[$i]; // Это штука в принципе ничего не выводит...
echo implode('<br>', $out); // А это результат, но выглядит он как count($fila) строчек с надписью "Array",
echo "<br>"; // разделенных переводом строки...
}
}
};
?>

Вообщем, проблема описана в комметариях к коду.
Еще есть проблема о том, как сообщить юзверю, что поиск ничего не нашел, т.е. куда ставить
CODE:
echo "Поиск не дал результатов</center>";

При этом использовать break; и exit(); нельзя, т.к. дальше есть еще вывод информации.
6. Furax - 20 Февраля, 2008 - 22:59:47 - перейти к сообщению
Э-м-м... А вот это зачем? Почему просто не поставить кнопку submit?
CODE:
<a href="index.php" onclick="document.find.submit(); return false">Проверить >>></a>


А что сие значит (я имею в виду регулярное выражение)? Откуда вообще октоторпы?
CODE:
preg_match("#[^A-Za-z\-]#is",$slovo)
Если это тест на допустимость символов, то я бы сделал так:
CODE:
preg_match('/[^A-Za-z\-А-Яа-я]/',$slovo)


Ещё вопрос: зачем разбиение по строкам при чтении файла, если мы потом ищем всё равно в каждой строке? В каждой строке-то можно и без регулярных выражений искать... Лучше искать сразу везде! Исключение составляют случаи, когда база настолько большая, что не входит в выделяемый скрипту объём оперативной памяти.

Регулярное выражение в preg_match_all составлено неправильно: оно ищет следующую последовательность (записывай): границу слова; любое количество любых символов; пробел; введённое пользователем слово; пробел; любое количество любых символов; границу слова. Кроме того, поскольку строка заключена в двойные кавычки, слэши надо дублировать.

Исправленный мною код выглядит вот так:
CODE:
$fila = file_get_contents("pages/db/a.dat");
if (preg_match_all("/\\b(\\S*$slovo\\S*)\\b/i", $fila, $out, PREG_PATTERN_ORDER))
{
echo implode('<br>', $out[1]);
}
else
{
echo 'Ничего не найдено';
}
Здесь поиск идёт сразу во всём файле, согласованные строки лежат в массиве $out[1]. Кроме того, я добавил ключ i к регулярному выражению, дабы поиск шёл независимо от регистра.
7. UFO - 21 Февраля, 2008 - 15:03:52 - перейти к сообщению
Большое спасибо, Furax! Реально помог написать скрипт Улыбка
Цитата:
Э-м-м... А вот это зачем? Почему просто не поставить кнопку submit?

Ссылкой красивее - работает так же как кнопка, но выглядит ссылкой, это чисто понты, дизайн, я и сам понимаю, что так проблем больше, но концепция сайта требует ссылку, а не привычную кнопку.
Цитата:
А что сие значит (я имею в виду регулярное выражение)? Откуда вообще октоторпы?

Просто проверка на введенные символы, чтобы не было запрещенных символов. Скопировал откуда-то давно еще, поэтому и пользуюсь везде этим вариантом. Всегда работало правильно.
Цитата:
Ещё вопрос: зачем разбиение по строкам при чтении файла, если мы потом ищем всё равно в каждой строке? В каждой строке-то можно и без регулярных выражений искать... Лучше искать сразу везде! Исключение составляют случаи, когда база настолько большая, что не входит в выделяемый скрипту объём оперативной памяти.

Я просто хотел создать цикл от i до кол-ва строк в файле, чтобы сравнивать каждую строку в файле с введенным словом в поле, если совпадает - выводим строку из файла на экран. Думал, что алгоритм такой.
Цитата:
Регулярное выражение в preg_match_all составлено неправильно

Ага, в этом была большая проблема - написать граммотно функцию.

Вообщем, еще раз спасибо, все работает как надо Улыбка Подмигивание
Респект Закатив глазки
8. UFO - 22 Февраля, 2008 - 15:19:36 - перейти к сообщению
В процессе работы скрипта возник следующий вопрос: можно ли как-либо сделать, чтобы если введенный запрос содержит знак "*", то в поиске этот символ заменяется на последовательность от a до z? Например, поисковый запрос **b* - поиск ищет в списке все слова, имеющие вид символ_символ_b_символ. Может быть это есть в функции preg_math_all? Конечно, можно "*" заменить буквами в цикле и вставить в переменную, но это сложнее, чем готовое решение в виде функции PHP...
9. Furax - 23 Февраля, 2008 - 00:01:57 - перейти к сообщению
Перед моим кодом:
CODE:
$slovo = str_replace('*', '\w', $slovo);
Соответственно, регулярное выражение для проверки правильности ввода (которую нужно делать ещё до этой замены) перепишется так:
CODE:
'/[^A-Za-z\-А-Яа-я\*]/'
10. UFO - 23 Февраля, 2008 - 11:07:29 - перейти к сообщению
Furax, большое спасибо тебе Улыбка
Не думал, что так просто поиск можно модернизировать Улыбка

Форум на AlfaSpace.NET


Powered by ExBB
ExBB FM 1.0 RC1 by TvoyWeb.ru
InvisionExBB Style converted by Markus®

[Script Execution time: 0.0459]     [ Gzipped ]



Notice: ob_end_flush(): failed to send buffer of ob_gzhandler (1) in /home/tvoyweb/domains/tvoyweb.ru/public_html/forums/include/page_tail.php on line 33