Модераторы: ginnie

Поиск:

Ответ в темуСоздание новой темы Создание опроса
> Не учитывать совпадение при определенных условиях, нежелательные символы 
:(
    Опции темы
Akella
  Дата 25.5.2012, 09:15 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Творец
****


Профиль
Группа: Модератор
Сообщений: 18485
Регистрация: 14.5.2003
Где: Корусант

Репутация: нет
Всего: 329



Есть выражение для поиска номеров телефонов:
Код
(\d[\d-•() ]{6,17})|(/\d{3,3}/[\d-•() ]{6,17})


но в тексте часто встречается не только номер телефона, но и цена, или какой-нибудь номер, например, номер объявления
Цитата
м Голосеевская 3-7 мин., 64423457, дата: 25.05.2012

Цитата
тип: Монолитный, цена 154500 у.е. продам


Вопрос. Как построить выражение, которое будет пропускать такие вот совпадения, если в совпавшем тексте найден нежелательный(е) символ(ы)?
PM MAIL   Вверх
Pfailed
Дата 25.5.2012, 13:26 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 933
Регистрация: 19.7.2009

Репутация: 6
Всего: 39





--------------------
PM MAIL   Вверх
Akella
Дата 25.5.2012, 14:03 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Творец
****


Профиль
Группа: Модератор
Сообщений: 18485
Регистрация: 14.5.2003
Где: Корусант

Репутация: нет
Всего: 329



не доходит, а можно конкретнее?
PM MAIL   Вверх
Pfailed
Дата 25.5.2012, 17:59 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 933
Регистрация: 19.7.2009

Репутация: 6
Всего: 39



Например здесь мы ищем цифры. Но если перед цифрами знак номера, то такие цифры нам не подходят.
На выходе вторая match группа содержит 1234.
Код

'abc № 4444444 fff 1234' =~ /(?:(№\s*)|\b)(\d+)(*SKIP)(?(1)(*FAIL))/ or die;


Словами это выражение: 
(
  1-я альтернатива - найти знак номера, затем возможно пробелы
  2-я альтернатива просто разделитель отделяющий цифры
)
затем цифры, которые мы ищем
просим движок рег выражений не возвращаться на позицию до текущей если поиск потерпит неудачу
говорим что поиск неудачен если найдена 1-я альтернатива

Таким образом:
движок находит "№ 4444444" - 1-я альтернатива
получает указание что поиск неудачен - FAIL
возвратиться за 4444444 он уже не может - SKIP
ищет далее и находит уже 2-ю альтернативу "1234" (действительно тут нет знака номера)
2-я альтернатива - это не первая -> поиск успешен

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



--------------------
PM MAIL   Вверх
alezzz
Дата 25.5.2012, 20:48 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


сплю...
**


Профиль
Группа: Участник
Сообщений: 499
Регистрация: 17.8.2009

Репутация: 11
Всего: 14



а возле номера телефона есть за что зацепться, например "тел." или код города в скобках?
не в тему, недочитал и непонял суть вопроса.

Это сообщение отредактировал(а) alezzz - 25.5.2012, 23:30
PM MAIL   Вверх
Akella
Дата 26.5.2012, 19:15 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Творец
****


Профиль
Группа: Модератор
Сообщений: 18485
Регистрация: 14.5.2003
Где: Корусант

Репутация: нет
Всего: 329



Цитата(alezzz @  25.5.2012,  20:48 Найти цитируемый пост)
а возле номера телефона есть за что зацепться, например "тел." или код города в скобках?


к сожалению часто бывает так, что нет никаких других признаков, того же признака тел не бывает иной раз :(
PM MAIL   Вверх
Akella
Дата 26.5.2012, 19:45 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Творец
****


Профиль
Группа: Модератор
Сообщений: 18485
Регистрация: 14.5.2003
Где: Корусант

Репутация: нет
Всего: 329



а как насчет просмотра вперед или назад
http://ru2.php.net/manual/ru/regexp.reference.assertions.php

(?<=bullock|donkey)
PM MAIL   Вверх
Pfailed
Дата 26.5.2012, 21:17 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 933
Регистрация: 19.7.2009

Репутация: 6
Всего: 39



Просмотр вперед годится, но просмотр назад в Perl должен быть фиксированой длинны, т.е никаких "*" или "+". Хотя в некоторых других языках, .Net например, такого ограничения нет.


--------------------
PM MAIL   Вверх
Akella
Дата 21.6.2012, 13:33 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Творец
****


Профиль
Группа: Модератор
Сообщений: 18485
Регистрация: 14.5.2003
Где: Корусант

Репутация: нет
Всего: 329



Не понял, что не так.
Вот выражение
Код
(?!№)\d[\d-•() ]{6,17}|(?!№)/\d{3,3}/[\d-•() ]{6,17}


Вот текст:
Цитата
Смирнова-Ласточкина, . ТЛФ: +380-67-8763116,  цена: 7 000 грн.,  (067)8763116P.S. Возможна сдачи квартиры под EURO-2012 Call., №68651705, дата: 20.06.2012


Выражение находит все три группы цифр, в том числе и 68651705, хотя это нужно пропускать

Что не так в этом выражении?
PM MAIL   Вверх
DurRandir
Дата 21.6.2012, 16:05 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 335
Регистрация: 27.9.2009

Репутация: 2
Всего: 17



Много почему))

1. Потому что ?! - это look-ahead assertion. А look-behind - это ?<!
2. Заменили, отлично. Но теперь матчинг для выражения №1234567 будет начинаться не с позиции №-->1<--2345, а с позиции №1-->2<--345, т.е. просто пропускает 1ю цифру. Поэтому добавим ещё одно условие - ?<!\d

Итого, получается что-то вроде (+я свернул общий хвост у выражений)
Код

 (?<!№)(?<!\d)(?:\d|\/\d{3,3}\/)[\d-() ]{6,17}


Это сообщение отредактировал(а) DurRandir - 21.6.2012, 16:06
PM   Вверх
Akella
Дата 21.6.2012, 16:14 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Творец
****


Профиль
Группа: Модератор
Сообщений: 18485
Регистрация: 14.5.2003
Где: Корусант

Репутация: нет
Всего: 329



Цитата(DurRandir @  21.6.2012,  16:05 Найти цитируемый пост)
(?<!№)(?<!\d)(?:\d|\/\d{3,3}\/)[\d-() ]{6,17}


всё равно находит
PM MAIL   Вверх
DurRandir
Дата 21.6.2012, 18:11 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 335
Регистрация: 27.9.2009

Репутация: 2
Всего: 17



Код

print "$_\n" for ('abc: +380-67-8763116, fsdfds, (067)8763116P.S. EURO-2012 Call., #68651705, dare 20.06.2012' =~ /(?<!#)(?<!\d)(?:\d|\/\d{3,3}\/)[\d-() ]{6,17}/g);

380-67-8763116
067)8763116

Я проверял на приведённой строке. Если какие-то другие данные - покажите.

Это сообщение отредактировал(а) DurRandir - 21.6.2012, 18:11
PM   Вверх
Akella
Дата 22.6.2012, 08:49 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Творец
****


Профиль
Группа: Модератор
Сообщений: 18485
Регистрация: 14.5.2003
Где: Корусант

Репутация: нет
Всего: 329



Цитата(DurRandir @  21.6.2012,  18:11 Найти цитируемый пост)
#68651705


у меня №, а не #

Добавлено через 48 секунд
Цитата(DurRandir @  21.6.2012,  16:05 Найти цитируемый пост)
Но теперь матчинг для выражения №1234567 будет начинаться не с позиции №-->1<--2345, а с позиции №1-->2<--345, т.е. просто пропускает 1ю цифру.

да, это я уже ещё вчера понял :(
PM MAIL   Вверх
Akella
Дата 22.6.2012, 09:08 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Творец
****


Профиль
Группа: Модератор
Сообщений: 18485
Регистрация: 14.5.2003
Где: Корусант

Репутация: нет
Всего: 329



Цитата(DurRandir @  21.6.2012,  18:11 Найти цитируемый пост)
print "$_\n" for ('abc: +380-67-8763116, fsdfds, (067)8763116P.S. EURO-2012 Call., #68651705, dare 20.06.2012' =~ /(?<!#)(?<!\d)(?:\d|\/\d{3,3}\/)[\d-() ]{6,17}/g);


Что-то у Вас тут напутано со скобками, как мне кажется

Добавлено через 1 минуту и 45 секунд
Вот это выражение вообще ничего ненаходит:
Код
(?<!#)(?<!\d)(?:\d|\/\d{3,3}\/)[\d-() ]{6,17}/g


Добавлено через 2 минуты и 25 секунд
а вот это работает: 
Код

(?<!#)(?<!\d)(?:\d|\/\d{3,3}\/)[\d-() ]{6,17}


Добавлено через 3 минуты и 35 секунд
Но всё равно находит: 

user posted image

Добавлено через 3 минуты и 47 секунд
Может дело в знаке ?

Добавлено через 4 минуты и 38 секунд
Да, действительно, если изменить в тексте объявления № на # и в выражении, то всё ок
PM MAIL   Вверх
DurRandir
Дата 22.6.2012, 14:14 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 335
Регистрация: 27.9.2009

Репутация: 2
Всего: 17



>Вот это выражение вообще ничего ненаходит
А вы не в перле смотрите, судя по скриншоту. Там концовка - /g - модификатор поиска всех совпадений, и требует стартового слеша / - они играют роль скобок-ограничителей.

>всё равно находит
Возможно, проблема в юникоде/кодировках? Я потому и проверял на ASCII-строке, чтобы это не влияло.
PM   Вверх
Akella
Дата 22.6.2012, 14:39 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Творец
****


Профиль
Группа: Модератор
Сообщений: 18485
Регистрация: 14.5.2003
Где: Корусант

Репутация: нет
Всего: 329



ну да, наверное, у буржуев ведь нет знака №

Добавлено через 11 секунд
и программа не юникодная

Добавлено через 39 секунд
в общем я перешёл на #, пока что
PM MAIL   Вверх
Akella
Дата 12.4.2013, 14:52 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Творец
****


Профиль
Группа: Модератор
Сообщений: 18485
Регистрация: 14.5.2003
Где: Корусант

Репутация: нет
Всего: 329



Хочу поднять тему, т.к. есть ещё проблема.
В тексте объявлений есть телефоны.
А также есть вот такой текст:  решения соответствуют требованиями СНиП 31-01-2003 Здания 

Получается так, что выделенная группа цифр определяется, как номер телефона.
Можно что-то придумать такое, что если перед номером есть слово: "СНиП ", то игнорировать найденный текст?
PM MAIL   Вверх
Pfailed
Дата 12.4.2013, 15:36 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 933
Регистрация: 19.7.2009

Репутация: 6
Всего: 39



Как была решена предыдущая проблема?

Это сообщение отредактировал(а) Pfailed - 12.4.2013, 15:51


--------------------
PM MAIL   Вверх
Akella
Дата 12.4.2013, 16:21 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Творец
****


Профиль
Группа: Модератор
Сообщений: 18485
Регистрация: 14.5.2003
Где: Корусант

Репутация: нет
Всего: 329



Цитата(Akella @  22.6.2012,  09:08 Найти цитируемый пост)
а вот это работает: 
Выделить всёБез подсветки
1:
    
(?<!#)(?<!\d)(?:\d|\/\d{3,3}\/)[\d-() ]{6,17}


ну с одним символом проблемы нет, а как задать конкретное слово? Например, "СНиП "
PM MAIL   Вверх
Pfailed
Дата 12.4.2013, 17:18 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 933
Регистрация: 19.7.2009

Репутация: 6
Всего: 39



На мой взгляд некорректное выражение. Удовлетворяет строке: решения соответствуют требованиями #01-01-2003 Здания.
А должно ли?

Это сообщение отредактировал(а) Pfailed - 12.4.2013, 17:28


--------------------
PM MAIL   Вверх
DurRandir
Дата 12.4.2013, 18:16 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 335
Регистрация: 27.9.2009

Репутация: 2
Всего: 17



Я бы чуть по другому сделал. Т.к. перед датой может не только "СНИП" идти (и придётся составлять список слов-исключений - регулярка расползётся быстро), я бы вырезал \d{2}-\d{2}-\d{4} как невалидный формат (никто так телефон не делит). Т.е. либо задал для хвоста [\d-() ]{6,17} более строгий формат, либо добавил соответствующий assertion: (?!\d{2,2}-\d{2,2}-\d{4,4}). Итого:

Код

(?<!#)(?<!\d)(?!\d{2}-\d{2}-\d{4})(?:\d|\/\d{3,3}\/)[\d-() ]{6,17}


*добавление* а оно же начнёт матчиться после -01-2003
В общем, лучше уточнить валидный формат или делать доп. проверку *после* поиска и выкидывать такие совпадения. 

Т.к. я не уверен, что даже нечто в духе 

Код

(?<![-#\d])(?!\d{2}-\d{2}-\d{4})(?:\d|\/\d{3,3}\/)[\d-() ]{6,17}


не зацепит лишнего

Это сообщение отредактировал(а) DurRandir - 12.4.2013, 18:22
PM   Вверх
Pfailed
Дата 12.4.2013, 18:24 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 933
Регистрация: 19.7.2009

Репутация: 6
Всего: 39



А в чём фишка писать \d{n,n}? Разве это не эквивалентно \d{n}?

Добавлено через 6 минут и 10 секунд
Цитата(DurRandir @  12.4.2013,  18:16 Найти цитируемый пост)
не зацепит лишнего

Но и не отработает на валидной (по условию) строке: решения соответствуют требованиями -01-01-2003 Здания


--------------------
PM MAIL   Вверх
Pfailed
Дата 12.4.2013, 18:40 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 933
Регистрация: 19.7.2009

Репутация: 6
Всего: 39



Вариация на тему моего первого поста в этой теме
Код

/((?:#|СНиП)\s*(?:\d|\/\d{3,3}\/)[\d-() ]{6,17})|(\b(?:\d|\/\d{3,3}\/)[\d-() ]{6,17})/

Уже в коде смотрим на вторую match группу. Если она определена -- берем ее значение. Если не определена -- переходим на следующую итерацию.

Это сообщение отредактировал(а) Pfailed - 12.4.2013, 18:44


--------------------
PM MAIL   Вверх
DurRandir
Дата 12.4.2013, 18:41 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 335
Регистрация: 27.9.2009

Репутация: 2
Всего: 17



Цитата
А в чём фишка писать \d{n,n}? Разве это не эквивалентно \d{n}?

Да я не везде исправил. Эквивалентно)

Цитата
Но и не отработает на валидной (по условию) строке: решения соответствуют требованиями -01-01-2003 Здания 

"Если у вас есть проблема, и вы собираетесь решать ее с использованием регулярных выражений, то у вас есть две проблемы" в полный рост, в общем то) Можно только гадать, подойдёт или не подойдёт под реальные данные, которые есть у Akella.

Это сообщение отредактировал(а) DurRandir - 12.4.2013, 18:42
PM   Вверх
Akella
Дата 13.4.2013, 12:36 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Творец
****


Профиль
Группа: Модератор
Сообщений: 18485
Регистрация: 14.5.2003
Где: Корусант

Репутация: нет
Всего: 329



Цитата(Pfailed @ 12.4.2013,  18:40)
Вариация на тему моего первого поста в этой теме
Код

/((?:#|СНиП)\s*(?:\d|\/\d{3,3}\/)[\d-() ]{6,17})|(\b(?:\d|\/\d{3,3}\/)[\d-() ]{6,17})/

Уже в коде смотрим на вторую match группу. Если она определена -- берем ее значение. Если не определена -- переходим на следующую итерацию.

Не то.

user posted image

а НЕ должно находить

Добавлено через 9 минут и 49 секунд
Цитата(DurRandir @  12.4.2013,  18:16 Найти цитируемый пост)
(?<![-#\d])(?!\d{2}-\d{2}-\d{4})(?:\d|\/\d{3,3}\/)[\d-() ]{6,17}


а вот это уже норм  smile

Добавлено через 10 минут и 8 секунд
Можно его словесно расшифровать?
PM MAIL   Вверх
Pfailed
Дата 13.4.2013, 15:02 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 933
Регистрация: 19.7.2009

Репутация: 6
Всего: 39



Цитата(Akella @  13.4.2013,  12:36 Найти цитируемый пост)
а НЕ должно находить

В какой match группе нашлось? Я же написал вам, что нужно смотреть только на вторую match группу.
Все исключения в первую match группу, все подходящие во вторую.


--------------------
PM MAIL   Вверх
DurRandir
Дата 14.4.2013, 21:31 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 335
Регистрация: 27.9.2009

Репутация: 2
Всего: 17



Цитата
Можно его словесно расшифровать? 

Я в том посте постарался описать, как конструировать. Оно состоит из 3х частей - двух отрицательных якорей:

(?<!) - не начинать матчинг, если до позиции стоит -#\d
(?!) - если строка дальше попадает под формат d{2}-\d{2}-\d{4}, то так же не начинать матчинг

и потом положительная проверка под подходящий формат
PM   Вверх
Akella
  Дата 15.4.2013, 09:01 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Творец
****


Профиль
Группа: Модератор
Сообщений: 18485
Регистрация: 14.5.2003
Где: Корусант

Репутация: нет
Всего: 329



Цитата(Pfailed @  13.4.2013,  15:02 Найти цитируемый пост)
В какой match группе нашлось? Я же написал вам, что нужно смотреть только на вторую match группу.


К сожалению, "смотреть" только туда или только сюда - не подходит, потому что в одном случае будет это выражение, а в другом случае будет другое выражение, но программа одна на всех, как говорится. Можно менять только образец (выражение поиска).
PM MAIL   Вверх
tishaishii
Дата 14.9.2018, 20:36 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Создатель
***


Профиль
Группа: Завсегдатай
Сообщений: 1262
Регистрация: 14.2.2006
Где: Москва

Репутация: нет
Всего: 8



Создавал такое рег.выр. импирически около 3х лет. Задача была вынимать объявления из отсканированных и распознанных объявлений, преобразованных в HTML. И нужно было искать номера телефонов в БД, чтобы показывать, обработан ли податчик объявления.

В общем, импирически, рег.выр. хранился в отдельном файле около 2х кб + дополнительный анализ подстрок.
PM MAIL ICQ Skype   Вверх
Страницы: (2) [Все] 1 2 
Ответ в темуСоздание новой темы Создание опроса
0 Пользователей читают эту тему (0 Гостей и 0 Скрытых Пользователей)
0 Пользователей:
« Предыдущая тема | Perl: Регулярные выражения | Следующая тема »


 




[ Время генерации скрипта: 0.1998 ]   [ Использовано запросов: 22 ]   [ GZIP включён ]


Реклама на сайте     Информационное спонсорство

 
По вопросам размещения рекламы пишите на vladimir(sobaka)vingrad.ru
Отказ от ответственности     Powered by Invision Power Board(R) 1.3 © 2003  IPS, Inc.