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

Warning: Invalid argument supplied for foreach() in /home/admin/public_html/forum/topic.php on line 737
Форумы портала PHP.SU :: Шаблон к preg_match

 PHP.SU

Программирование на PHP, MySQL и другие веб-технологии
PHP.SU Портал     На главную страницу форума Главная     Помощь Помощь     Поиск Поиск     Поиск Яндекс Поиск Яндекс     Вакансии  Пользователи Пользователи


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

> Описание: Как правильно шаблон составить?
Dantesik
Отправлено: 09 Января, 2008 - 17:23:51
Post Id


Новичок


Покинул форум
Сообщений всего: 4
Дата рег-ции: Янв. 2008  
Откуда: Владивосток, Россия


Помог: 0 раз(а)




Господа. Подскажите какой-нить мануальчик по составлению шаблона, а то везде общая информация, а для меня это пока темный лес.

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

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

Если пример - то вообще буду примного благодарен. Заранее спасибо.
 
 Top
evgenijj
Отправлено: 09 Января, 2008 - 18:35:06
Post Id



Участник


Покинул форум
Сообщений всего: 1212
Дата рег-ции: Авг. 2006  
Откуда: Москва


Помог: 10 раз(а)




Ничего не понял.

Есть текст, и в тексте встречаются строки
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 - цифра, считаем номером телефона. Все остальное - нет. Тогда можно будет подумать.
 
 Top
Dantesik
Отправлено: 09 Января, 2008 - 23:41:25
Post Id


Новичок


Покинул форум
Сообщений всего: 4
Дата рег-ции: Янв. 2008  
Откуда: Владивосток, Россия


Помог: 0 раз(а)




Так я про это и говорю. Есть список возможного написания телефонов в объявлении. Там просто на сайте идет подсчет кол-ва объявлений по телефону и соответственно все пишут телефоны как попало - лишь бы не платить =) Халява.
Почему на сайте стандартную форму не сделают - хз. Ну это их дело. Приходится за них это делать, но для других целей.

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

В базе забито 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})
 
 Top
evgenijj
Отправлено: 10 Января, 2008 - 09:56:50
Post Id



Участник


Покинул форум
Сообщений всего: 1212
Дата рег-ции: Авг. 2006  
Откуда: Москва


Помог: 10 раз(а)




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] ). Надо еще подумать.

Догадался, почему. Исправил.
 
 Top
Dantesik
Отправлено: 10 Января, 2008 - 10:22:21
Post Id


Новичок


Покинул форум
Сообщений всего: 4
Дата рег-ции: Янв. 2008  
Откуда: Владивосток, Россия


Помог: 0 раз(а)




Спасибо огромное. Буду разбираться.
 
 Top
evgenijj
Отправлено: 10 Января, 2008 - 10:38:01
Post Id



Участник


Покинул форум
Сообщений всего: 1212
Дата рег-ции: Авг. 2006  
Откуда: Москва


Помог: 10 раз(а)




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
будет найден два раза - сначала как мобильный, потом как городской. Надо бы делать так: удалять из сообщения найденные номера мобильных, а уже потом в этом урезанном объявлении искать городские номера.
 
 Top
Dantesik
Отправлено: 10 Января, 2008 - 12:21:29
Post Id


Новичок


Покинул форум
Сообщений всего: 4
Дата рег-ции: Янв. 2008  
Откуда: Владивосток, Россия


Помог: 0 раз(а)




Так-с.
Еще раз спасибо. Есть правда небольшой трабл.
Если добавить при поиске городского номера в начало и конец [^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(Добавление)
Не обновил форум. Не заметил сообщение.
 
 Top
evgenijj
Отправлено: 10 Января, 2008 - 13:53:14
Post Id



Участник


Покинул форум
Сообщений всего: 1212
Дата рег-ции: Авг. 2006  
Откуда: Москва


Помог: 10 раз(а)




Вот еще один вариант - с исправлениями и дополнениями. После того, как я нашел мобильные номера, я вырезаю их из сообщения и потом ищу городские
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. Вместе с дефисом - уже три.
 
 Top
pmdesign
Отправлено: 02 Февраля, 2010 - 08:43:39
Post Id



Новичок


Покинул форум
Сообщений всего: 10
Дата рег-ции: Июнь 2009  
Откуда: Юрга


Помог: 0 раз(а)




а может сначала удалить все символы кроме цифр, а потом просто искать или принципиально нужно работать с регулярными выражениями?
 
 Top
EuGen Администратор
Отправлено: 02 Февраля, 2010 - 10:46:10
Post Id


Профессионал


Покинул форум
Сообщений всего: 9095
Дата рег-ции: Июнь 2007  
Откуда: Berlin


Помог: 707 раз(а)




А, быть может, сначала посмотреть на дату последнего сообщения в теме?
Тема закрыта!


-----
Есть в мире две бесконечные вещи - это Вселенная и человеческая глупость. Но насчет первой .. я не уверен.
 
 Top
Страниц (1): [1]
Сейчас эту тему просматривают: 0 (гостей: 0, зарегистрированных: 0)
« Программирование на PHP »


Все гости форума могут просматривать этот раздел.
Только зарегистрированные пользователи могут создавать новые темы в этом разделе.
Только зарегистрированные пользователи могут отвечать на сообщения в этом разделе.
 



Powered by PHP  Powered By MySQL  Powered by Nginx  Valid CSS  RSS

 
Powered by ExBB FM 1.0 RC1. InvisionExBB