Warning: Cannot use a scalar value as an array in /home/admin/public_html/forum/include/fm.class.php on line 757

Warning: Invalid argument supplied for foreach() in /home/admin/public_html/forum/include/fm.class.php on line 770
Форумы портала PHP.SU :: Версия для печати :: Шаблон к preg_match
Форумы портала PHP.SU » PHP » Программирование на PHP » Шаблон к preg_match

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

1. Dantesik - 09 Января, 2008 - 17:23:51 - перейти к сообщению
Господа. Подскажите какой-нить мануальчик по составлению шаблона, а то везде общая информация, а для меня это пока темный лес.

Вкратце ситуация. Есть база номеров телефонов. Могут быть XXXXXX (городской номер. 6 цифр не пугайтесь. Город у нас маленький =)) и сотовый XXXXXXXXXX (10 цифр т.е. без +7 или 8). Ежедневно скачивается несколько тысяч объявлений, где номер телефона может быть в любом формате.
Например XX XX XX или XXX - XXX или XXX XXX-XX XX. Вообщем у пользователей хватает смекалки как усложнить работу =) Доступа к редактированию ввода нет.

Вот и возникла необходимость выдергивать из объявления номера телефонов и потом убирая все посторонние символы сравнивать с "чистым" в базе. Так. Телефонов может быть несколько. И еще в объявлении телефон может быть в любом месте. Как в начале, так и в конце. Грамотно написать шаблон. Даже один пока не получается. Вот помощи и прошу.

Если пример - то вообще буду примного благодарен. Заранее спасибо.
2. evgenijj - 09 Января, 2008 - 18:35:06 - перейти к сообщению
Ничего не понял.

Есть текст, и в тексте встречаются строки
123456
12 34 56
12-34-56
1234567890
123 456-78-90
(123) 4567890
123-456-78-90
(123) 4567890
Вполне возможно, с ошибками
(123 4567890
123) 456-78-90
А еще какой-нибудь оригинал напишет
123*456*78*90

Я вообще немного разбираюсь в рег. выражениях, но за такую задачу не возмусь: "Пойди туда, не знаю куда, принеси то, не знаю что."

Надо формализовать задачу. Например, все, что имеет формат
xxxxxx
xx-xx-xx
xx xx xx
xxxxxxxxxx
xxx-xxx-xx-xx
xxx xxx xx xx
xxx xxx-xx-xx
xxx xxx-xxxx
где x - цифра, считаем номером телефона. Все остальное - нет. Тогда можно будет подумать.
3. Dantesik - 09 Января, 2008 - 23:41:25 - перейти к сообщению
Так я про это и говорю. Есть список возможного написания телефонов в объявлении. Там просто на сайте идет подсчет кол-ва объявлений по телефону и соответственно все пишут телефоны как попало - лишь бы не платить =) Халява.
Почему на сайте стандартную форму не сделают - хз. Ну это их дело. Приходится за них это делать, но для других целей.

Делалось так.

В базе забито XXXXXX или XXXXXXXXXX. Т.е. только цифры.

CODE (text):
скопировать код в буфер обмена
  1. //Для сотовых
  2. preg_match("|([0-9]{3})([0-9]{3})([0-9]{2})([0-9]{2})|i",$zap['telef'], $r1);
  3. //xxx-xxx-xx-xx
  4. $pat[0] = $r1[1].$r1[2].$r1[3].$r1[4];
  5. $pat[1] = $r1[1].' '.$r1[2].' '.$r1[3].' '.$r1[4];//xxx xxx xx xx
  6. $pat[2] = $r1[1].' '.$r1[2].' '.$r1[3].'-'.$r1[4];//xxx xxx xx-xx
  7. $pat[3] = $r1[1].' '.$r1[2].'-'.$r1[3].'-'.$r1[4];//xxx xxx-xx-xx
  8. $pat[4] = $r1[1].'-'.$r1[2].'-'.$r1[3].'-'.$r1[4];//xxx-xxx-xx-xx
  9. $pat[5] = $r1[1].' '.$r1[2].$r1[3].$r1[4];//xxx xxxxxxx
  10. $pat[6] = $r1[1].'-'.$r1[2].$r1[3].$r1[4];//xxx-xxxxxxx
  11. $pat[7] = $r1[1].' '.$r1[2].' '.$r1[3].$r1[4];//xxx xxx xxxx
  12. $pat[8] = $r1[1].' '.$r1[2].'-'.$r1[3].$r1[4];//xxx xxx-xxxx
  13. $pat[9] = $r1[1].'_'.$r1[2].'_'.$r1[3].$r1[4];//xxx_xxx_xxxx
  14.  
  15. //Для городских
  16. preg_match("|([0-9]{2})([0-9]{2})([0-9]{2})|i",$zap['telef'], $r1);
  17. preg_match("|([0-9]{3})([0-9]{3})|i",$zap['telef'], $r2);
  18.  
  19. //xx-xx-xx
  20. $pat[0] = $r1[1].$r1[2].$r1[3];
  21. $pat[1] = $r1[1]." ".$r1[2]." ".$r1[3];
  22. $pat[2] = $r1[1]."-".$r1[2]."-".$r1[3];
  23. $pat[3] = $r1[1].' — '.$r1[2].' — '.$r1[3];
  24. $pat[4] = $r1[1].'—'.$r1[2].'—'.$r1[3];
  25.                  
  26. //xxx-xxx
  27. $pat[5] = $r2[1]." ".$r2[2];
  28. $pat[6] = $r2[1].'-'.$r2[2];
  29. $pat[7] = $r2[1].' — '.$r2[2];
  30. $pat[8] = $r2[1].'—'.$r2[2];
  31.                  
  32. //xx-xxxx
  33. $pat[9] = $r1[1].' '.$r1[2].$r1[3];
  34. $pat[10] = $r1[1].'-'.$r1[2].$r1[3];
  35. $pat[11] = $r1[1].'—'.$r1[2].$r1[3];
  36. $pat[12] = $r1[1].' — '.$r1[2].$r1[3];
  37.          
  38. //xxxx-xx
  39. $pat[13] = $r1[1].$r1[2].' '.$r1[3];
  40. $pat[14] = $r1[1].$r1[2].'-'.$r1[3];
  41. $pat[15] = $r1[1].$r1[2].'—'.$r1[3];
  42. $pat[16] = $r1[1].$r1[2].' — '.$r1[3];


Соответственно после этого в скачанном объявлении ищется соответствие $pat. И так несколько тысяч раз пробегая по базе телефонов пока соответствие не найдено или база не кончилась. На мой взгляд - не рационально. Однако времени было в обрез и выбирать не приходилось (с php 1 раз работал =)).

Теперь по данным шаблонам можно выдернуть сам телефон из объявления и искать соответствие mysql запросом. Мне кажеться будет намного быстрее =).

Так немного поколдовал для городских вот что получилось
([0-9]{1}[^0-9]{1,3}[0-9]{5}) |
([0-9]{5}[^0-9]{1,3}[0-9]{1}) |
([0-9]{3}[^0-9]{1,3}[0-9]{3}) |
([0-9]{2}[^0-9]{0,3}[0-9]{2}[^0-9]{0,3}[0-9]{2})
4. evgenijj - 10 Января, 2008 - 09:56:50 - перейти к сообщению
PHP:
скопировать код в буфер обмена
  1.  
  2. $text = 'Таблица – конструкция базы данных, которая состоит из столбцов, 123-456-78-90 содержащих строки данных.
  3. Обычно таблицы созданы для того, чтобы содержать 6783452578 связанную информацию. В пределах той же самой базы
  4. данных могут быть созданы несколько таблиц.
  5.  
  6. Каждый столбец представляет собой атрибут или 567890 совокупность атрибутов объектов, например идентификационные
  7. номера служащих, рост, цвет машин и т.п. Часто в отношении 987-123 столбца используется термин поле с указанием
  8. имени, например "в поле Name". Поле строки является минимальным элементом таблицы. Каждый столбец в таблице имеет
  9. определенное имя, тип данных и размер. Имена столбцов 123 456-78-92 должны быть уникальны в пределах таблицы.
  10.  
  11. Каждая строка (или запись) представляет собой 87-22-16 совокупность атрибутов конкретного объекта, например, в 123-
  12. 456 строке может содержаться идентификационный номер служащего, размер его зарплаты, год его рождения и т.д.
  13. Строки таблиц не имеют названий. Чтобы обратиться к конкретной 745 123-4567 строке, пользователю необходимо
  14. указать какой-то атрибут (или набор атрибутов), уникально ее идентифицирующий.';
  15. // Ищем в объявлении мобильные телефоны
  16. $pattern = '#([0-9]{3})[^0-9]{0,2}([0-9]{3})[^0-9]{0,2}([0-9]{2})[^0-9]{0,2}([0-9]{2})#';
  17. preg_match_all( $pattern, $text, $matches );
  18. $cnt = count( $matches[0] );
  19. for ( $i = 0; $i < $cnt; $i++ ) {
  20.   echo 'Найден номер мобильного телефона: '.$matches[0][$i].'<br/>';
  21.   $phones[] = $matches[1][$i].$matches[2][$i].$matches[3][$i].$matches[4][$i];
  22. }
  23. unset( $matches );
  24. echo '<hr>';
  25. // Ищем в объявлении городские телефоны
  26. $pattern = '#(?:([0-9]{3})[^0-9]{0,2}([0-9]{3}))|(?:([0-9]{2})[^0-9]{0,2}([0-9]{2})[^0-9]{0,2}([0-9]{2}))#';
  27. preg_match_all( $pattern, $text, $matches );
  28. $cnt = count( $matches[0] );
  29. for ( $i = 0; $i < $cnt; $i++ ) {
  30.   echo 'Найден номер городского телефона: '.$matches[0][$i].'<br/>';
  31.   $phones[] = preg_replace( '#[^0-9]#', '', $matches[0][$i] );
  32. }
  33. echo '<hr>';
  34. foreach( $phones as $phone ) echo $phone.'<br/>';
  35.  

Результат
PHP:
скопировать код в буфер обмена
  1.  
  2. Найден номер мобильного телефона: 123-456-78-90
  3. Найден номер мобильного телефона: 6783452578
  4. Найден номер мобильного телефона: 123 456-78-92
  5. Найден номер мобильного телефона: 745 123-4567
  6. -------------------------------------------------------------
  7. Найден номер городского телефона: 123-456
  8. Найден номер городского телефона: 678345
  9. Найден номер городского телефона: 567890
  10. Найден номер городского телефона: 987-123
  11. Найден номер городского телефона: 123 456
  12. Найден номер городского телефона: 87-22-16
  13. Найден номер городского телефона: 745 123
  14. ------------------------------------------------------
  15. 1234567890
  16. 6783452578
  17. 1234567892
  18. 7451234567
  19. 123456
  20. 678345
  21. 567890
  22. 987123
  23. 123456
  24. 872216
  25. 745123
  26.  

Однако, фигня получилась - почему-то не работает preg_replace( '[^0-9]', '', $matches[0][$i] ). Надо еще подумать.

Догадался, почему. Исправил.
5. Dantesik - 10 Января, 2008 - 10:22:21 - перейти к сообщению
Спасибо огромное. Буду разбираться.
6. evgenijj - 10 Января, 2008 - 10:38:01 - перейти к сообщению
Dantesik пишет:
Спасибо огромное. Буду разбираться.

([0-9]{3}) - три цифры
[^0-9]{0,2} - 0,1 или 2 символа, кроме цифр. Я беру как max именно два, потому что может быть дефис, а потом пробел или превод строки
([0-9]{3}) - три цифры
[^0-9]{0,2} - 0,1 или 2 символа, кроме цифр
([0-9]{2}) - две цифры
[^0-9]{0,2} - 0,1 или 2 символа, кроме цифр
([0-9]{2}) - две цифры
Это будет соответствовать
xxxxxxxxxx
xxx xxx xx xx
xxx-xxx-xx-xx
xxx xxxxxxx
xxx xxx-xx-xx
и т.п.
Номера городских
(?:[0-9]{3}[^0-9]{0,2}[0-9]{3})|(?:[0-9]{2}[^0-9]{0,2}[0-9]{2}[^0-9]{0,2}[0-9]{2})
или так: [0-9]{3}[^0-9]{0,2}[0-9]{3}
xxx-xxx
xxxxxx
xxx xxx
Или так [0-9]{2}[^0-9]{0,2}[0-9]{2}[^0-9]{0,2}[0-9]{2}
xx xx xx
xx-xx-xx
xxxxxx

Вот, начал объяснять, и понял, что в моем решении есть ошибка. Номер телефона
123-456-78-90
123-456-78-90
будет найден два раза - сначала как мобильный, потом как городской. Надо бы делать так: удалять из сообщения найденные номера мобильных, а уже потом в этом урезанном объявлении искать городские номера.
7. Dantesik - 10 Января, 2008 - 12:21:29 - перейти к сообщению
Так-с.
Еще раз спасибо. Есть правда небольшой трабл.
Если добавить при поиске городского номера в начало и конец [^0-9]{0,2} это спасет от повтора:
Найден номер мобильного телефона: 6783452578
Найден номер городского телефона: 678345

Однако если номер будет записан, как 123-456-78-90
Выхватит 123-456, как городской, чего быть не должно.
Ну или 123 456-7788, 11-22-33.
Найдет три номера
сотовый 123 456-7788
городской 123-456
городской 11-22-33

array_search не подходит, ведь он на точное соответствие. Есть какая-нить функция? или по всему массиву бегать и делать strpos???





\n\n(Добавление)
Не обновил форум. Не заметил сообщение.
8. evgenijj - 10 Января, 2008 - 13:53:14 - перейти к сообщению
Вот еще один вариант - с исправлениями и дополнениями. После того, как я нашел мобильные номера, я вырезаю их из сообщения и потом ищу городские
PHP:
скопировать код в буфер обмена
  1.  
  2. $text = 'Таблица – конструкция базы данных, которая состоит из столбцов, 123-456-78-90 содержащих строки данных.
  3. Обычно таблицы созданы для того, чтобы содержать 678-3452578 связанную информацию. В пределах той же самой базы
  4. данных могут быть созданы несколько таблиц.
  5.  
  6. Каждый столбец представляет собой атрибут или 567-890 совокупность атрибутов объектов, например идентификационные
  7. номера служащих, рост, цвет машин и т.п. Часто в отношении 987-123 столбца используется термин поле с указанием
  8. имени, например "в поле Name". Поле строки является минимальным элементом таблицы. Каждый столбец в таблице имеет
  9. определенное имя, тип данных и размер. Имена столбцов 123 456-78-92 должны быть уникальны в пределах таблицы.
  10.  
  11. Каждая строка (или запись) представляет собой 87-22-16 совокупность атрибутов конкретного объекта, например, в 123-
  12. 456 строке может содержаться идентификационный номер служащего, размер его зарплаты, год его рождения и т.д.
  13. Строки таблиц не имеют названий. Чтобы обратиться к конкретной 745 123-4567 строке, пользователю необходимо
  14. указать какой-то атрибут (или набор атрибутов), уникально ее идентифицирующий.';
  15. // Ищем в объявлении мобильные телефоны
  16. $pattern = '#([0-9]{3})[^0-9]{0,3}([0-9]{3})[^0-9]{0,3}([0-9]{2})[^0-9]{0,3}([0-9]{2})#';
  17. preg_match_all( $pattern, $text, $matches );
  18. $cnt = count( $matches[0] );
  19. for ( $i = 0; $i < $cnt; $i++ ) {
  20.   echo 'Найден номер мобильного телефона: '.$matches[0][$i].'<br/>';
  21.   $phones[] = $matches[1][$i].$matches[2][$i].$matches[3][$i].$matches[4][$i];
  22. }
  23. $text = str_replace( $matches[0], '', $text );
  24. unset( $matches );
  25. echo '<hr>';
  26. // Ищем в объявлении городские телефоны
  27. $pattern = '#(?:[0-9]{3}[^0-9]{0,3}[0-9]{3})|(?:[0-9]{2}[^0-9]{0,3}[0-9]{2}[^0-9]{0,3}[0-9]{2})#';
  28. preg_match_all( $pattern, $text, $matches );
  29. $cnt = count( $matches[0] );
  30. for ( $i = 0; $i < $cnt; $i++ ) {
  31.   echo 'Найден номер городского телефона: '.$matches[0][$i].'<br/>';
  32.   $phones[] = preg_replace( '#[^0-9]#', '', $matches[0][$i] );
  33. }
  34. echo '<hr>';
  35. foreach( $phones as $phone ) echo $phone.'<br/>';
  36.  

Еще одно изменение - то что в качестве разделителя используется [^0-9]{0,3} а не [^0-9]{0,2} Шаблон [^0-9]{0,2} не находит соответствие если сразу после разделителя номера (например дефис) идет перевод строки. Возможно, это связано с тем, что в Windows новая строка \r\n. Вместе с дефисом - уже три.
9. pmdesign - 02 Февраля, 2010 - 08:43:39 - перейти к сообщению
а может сначала удалить все символы кроме цифр, а потом просто искать или принципиально нужно работать с регулярными выражениями?
10. EuGen - 02 Февраля, 2010 - 10:46:10 - перейти к сообщению
А, быть может, сначала посмотреть на дату последнего сообщения в теме?

 

Powered by ExBB FM 1.0 RC1