Модераторы: Aliance, skyboy, MoLeX, ksnk
  

Поиск:

Ответ в темуСоздание новой темы Создание опроса
> Волшебное регулярное выражение 
:(
    Опции темы
CyraxZ
Дата 7.8.2013, 18:23 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


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

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



Здравствуйте.
Есть строка, включающая фрагменты-разделители " AND ", " OR ", " NOT ", "(", ")". Например:
program AND fof AND NOT (5 OR 6 OR (8 AND ppp))

Из этой строки мне необходимо получить фрагменты:
program
fof
5
6
8
ppp

Дополнительные условия:
а) извлечённые фрагменты не должны иметь пробелов слева или справа (в середине могут)
б) регистр фрагментов-разделителей (" AND ", " OR ", " NOT ", "(", ")") неважен
в) если в строке фрагментов-разделителей не будет, то регулярное выражение должно вернуть всю исходную строку

г) Если рядом стоят OR/AND/NOT и круглая скобка, то между ними пробелов может не быть:
...OR(...
...AND(...
...NOT(...
...(NOT...
...)OR...
...)AND...
...)NOT...
...NOT)...
Во всех этих случаях фрагменты OR, AND, NOT, ), ( должны распознаваться как разделители. 

Каким должно быть регулярное выражение, чтобы извлечь эти фрагменты из строки ?
Заранее спасибо. 

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


Опытный
**


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

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



Сабжевое регулярное выражение мне нужно для использования в preg_replace: все отобранные фрагменты будут заменены на другие фрагменты, зависящие от исходных.
PM MAIL   Вверх
skyboy
Дата 7.8.2013, 21:35 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


неОпытный
****


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

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



смотри. у тебя есть "разделители". ты уже на верном пути. 
используй preg_split для разбивки строки.
и никакое волшебное регулярное выражение не надо: надо только описать твои разделители, добавив по бокам "\s+" для удаления лишних пробелов.
P.S. а сами "разделители" тебе точно не надо учитывать? то есть, что AND, что NOT — все равно? если не все равно, то все ж советую подумать над просто последовательным анализом вместо поиска волшебной регулярки: бьешь по пробелам или скобкам, а потом по очереди анализируешь очередной "токен" — и в случае совпадения с NOT/OR/AND делаешь что-то. или не делаешь.
PM MAIL   Вверх
CyraxZ
Дата 7.8.2013, 22:30 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


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

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



Цитата

используй preg_split для разбивки строки.
и никакое волшебное регулярное выражение не надо: надо только описать твои разделители, добавив по бокам "\s+" для удаления лишних пробелов.

Эта функция вернёт массив требуемых фрагментов. Но мы потеряем разделители.
А мне, как я уже написал, нужно в исходной строке заменить искомые фрагменты на более сложные, при этом оставив на своих местах все разделители.

Т.е. исходная строка:
program AND fof AND NOT (5 OR 6 OR (8 AND ppp))

Нужно получить:
более сложное выраж1 AND более сложное выраж2 AND NOT (более сложное выраж3 OR более сложное выраж4 OR (более сложное выраж5 AND более сложное выраж6))

Если сделать это функцией
preg_replace(регВыражение, ...$0..., исходнаяСтрока)
было бы здорово. Лаконично и изячно ))

Это сообщение отредактировал(а) CyraxZ - 7.8.2013, 22:31
PM MAIL   Вверх
skyboy
Дата 8.8.2013, 00:21 (ссылка) |    (голосов:1) Загрузка ... Загрузка ... Быстрая цитата Цитата


неОпытный
****


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

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



слушай. если у тебя замена безусловная, то сделай просто в несколько заходов: сначала разбить по AND и заменить каждую часть. затем — по OR. и так далее.
если замена происходит по результатам выполнения неких функций, то лучше сделать парсинг — разбить на токены.
или давай, все ж, полностью задачу, пускай и в упрощенном виде. текущий вариант "заменить что-то на что-то, учитывая разделители" не оправдывает сложности подхода.
в моем понимании, решать это регуляркой — это как считать регуляркой корректность закрытия скобок — в некоторых случаях возможно, но зачем городить огород?
PM MAIL   Вверх
Gold Dragon
Дата 9.8.2013, 07:40 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Призрачный
****


Профиль
Группа: Экс. модератор
Сообщений: 6753
Регистрация: 1.3.2004
Где: Россия, Тамбов

Репутация: 1
Всего: 71



небольшой набросок

Код

$matches = array();

// строка
$str = 'program AND fof AND NOT (5 OR 6 OR (8 AND ppp))';

// правило
$pattern = '#([\s]*and[\s]*|[\s]*not[\s]*|[\s]*or[\s]*|[\s]*\([\s]*|[\s]*\)[\s]*)#is';

// Получаем все разделители
preg_match_all($pattern, $str, $matches);
$a1 = $matches[1];

// Удаляем пробелы
// Можно обойти массив и удалить пробелы. Но думаю нет необходимости, проберы не мешают коду
// Если только двойные массивы потом удалить

// Получаем значения
$a2 = preg_split($pattern,$str, -1);


На выходе имеем
Код

array (
    0 => ' AND ',
    1 => ' AND ',
    2 => 'NOT ',
    3 => '(',
    4 => ' OR ',
    5 => ' OR ',
    6 => '(',
    7 => ' AND ',
    8 => ')',
    9 => ')'
  )

и 
Код

array (
  0 => 'program',
  1 => 'fof',
  2 => '',
  3 => '',
  4 => '5',
  5 => '6',
  6 => '',
  7 => '8',
  8 => 'ppp',
  9 => '',
  10 => ''
)



По индексам мы можем уже спокойно подставлять значения.. Например:
- Если второй массив длиннее, значит строка начинается со значения
- Если во втором случае [2] и [3] пустые, значит в первом случае [2] и [3] идут друг за другом

Добавлено @ 07:42
Но правило нужно доработать, т.к. могут попасться слова, в которых встречается часть, например "android". Здесь нужно проверять ещё дополнительно что перед AND и после нет букв. 

Что-то как-то так
Код

$pattern = '#([\s]*[^a-z]and[^a-z][\s]*|[\s]*[^a-z]not[^a-z][\s]*|[\s]*[^a-z]or[^a-z][\s]*|[\s]*\([\s]*|[\s]*\)[\s]*)#is';


Добавлено через 8 минут и 57 секунд
где-то ошибка в логике в последнем правило.. некоторые строчки пропускает
как правильно сказал skyboy, нужно по порядку делать замену. А то усложнение регулярки может привести к тормозам smile

Это сообщение отредактировал(а) Gold Dragon - 9.8.2013, 07:43


--------------------
Нельзя жить в прошлом, оно уже прошло.
Нельзя жить в будущем, оно ещё не наступило.
Нужно жить в настоящем, помня прошлое и думая о будущем!
PM MAIL WWW ICQ   Вверх
_zorn_
Дата 14.8.2013, 10:32 (ссылка) |    (голосов:1) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
***


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

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



Цитата
Some people, when confronted with a problem, think "I know, I’ll use regular expressions." Now they have two problems.

По моему как раз тот случай smile 

Почему не сделать обычным str_replace ?
Код

$query = str_replace(array('program',
                                          'fof',
                                          '5',
                                          '6',
                                          '8',
                                          'ppp'),
                                 array('более сложное выраж1',
                                          'более сложное выраж2',
                                          'более сложное выраж3',
                                          'более сложное выраж4',
                                          'более сложное выраж5',
                                          'более сложное выраж6'),$query);

Тут могут быть проблемы, если в исходной строке будет например '56', но про это в условии ничего не сказано и я осмелился предположить, что таких ситуаций не случится  smile 

Это сообщение отредактировал(а) _zorn_ - 14.8.2013, 10:46
PM MAIL   Вверх
krundetz
Дата 14.8.2013, 10:56 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Вечный странник
***


Профиль
Группа: Завсегдатай
Сообщений: 1400
Регистрация: 14.6.2007
Где: НН(Сормово)

Репутация: 1
Всего: 69



ХМ. А зачем здесь регулярные выражения? Лучше сделать токенайзер, а уже вокруг него построить синтаксический анализатор. В общем теория компиляции. Ключевое слово "Книга Дракона".


--------------------
!цензоры - Хранитель стратегической жидкости
Группа ТГВ
Группа Нижний Новгород
user posted image
PM MAIL   Вверх
Gold Dragon
Дата 14.8.2013, 21:08 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Призрачный
****


Профиль
Группа: Экс. модератор
Сообщений: 6753
Регистрация: 1.3.2004
Где: Россия, Тамбов

Репутация: 1
Всего: 71



Цитата(krundetz @  14.8.2013,  11:56 Найти цитируемый пост)
 Ключевое слово "Книга Дракона". 
это о чём?  smile 

Да ладно вам.. Вопрос изначально полный БРЕД! Просто интересная задачка, чисто по практиковаться в регулярках   smile 



--------------------
Нельзя жить в прошлом, оно уже прошло.
Нельзя жить в будущем, оно ещё не наступило.
Нужно жить в настоящем, помня прошлое и думая о будущем!
PM MAIL WWW ICQ   Вверх
krundetz
Дата 15.8.2013, 10:26 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Вечный странник
***


Профиль
Группа: Завсегдатай
Сообщений: 1400
Регистрация: 14.6.2007
Где: НН(Сормово)

Репутация: 1
Всего: 69



Цитата(Gold Dragon @  14.8.2013,  21:08 Найти цитируемый пост)
это о чём?

о теории компиляции.

Цитата(ru.wikipedia.org)

«Компиляторы: принципы, технологии и инструменты» — классический учебник по теории построения компиляторов под авторством Альфреда В. Ахо, Рави Сети[en] и Джеффри Д. Ульмана, известный также как «Книга дракона» (так как на обложке изображены дракон и рыцарь).


Цитата(Gold Dragon @  14.8.2013,  21:08 Найти цитируемый пост)

Да ладно вам.. Вопрос изначально полный БРЕД!

ну почему же, иногда требуется собственный интерпретатор

Это сообщение отредактировал(а) krundetz - 15.8.2013, 10:31


--------------------
!цензоры - Хранитель стратегической жидкости
Группа ТГВ
Группа Нижний Новгород
user posted image
PM MAIL   Вверх
  
Ответ в темуСоздание новой темы Создание опроса
1 Пользователей читают эту тему (1 Гостей и 0 Скрытых Пользователей)
0 Пользователей:
« Предыдущая тема | PHP: Тексты | Следующая тема »


 




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


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

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