LINUX.ORG.RU

[regexp][noob] Глупый вопрос по регулярке.


0

1

есть строка вида '*tag *tag2 *tag3 More text...'

Хочу получить список тегов и текст, например, ('tag', 'tag2', 'tag3','More text...')

Написал такое выражение '(?:\*([\w]+)(?:\s|))+[\s]+(.+)'

что то не очень работает, хотя в теории должно работать. засада в повторении группы, у меня всегда получается ('tag3','More text...'), т.е. только последний тег и текст.

Где я ошибся?

Если я правильно понял постановку задачи, с помощью только регулярных выражений такое невозможно, более правильно тут написать грамматику на yacc/bison

annoynimous ★★★★★ ()

описывается выражением (\*(\w+)\s+)*(.*)
но вытащить из одних и тех же скобок несколько выражений ИМХО невозможно

FollowTheRabbit ()
Ответ на: комментарий от annoynimous

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

Apkawa ()
Ответ на: комментарий от FollowTheRabbit

> *tag1 not_a_tag *tag2 *tag3 More text...

стартовый топик читал, нет?

arsi ★★★★★ ()
Ответ на: комментарий от arsi

Это всё ещё регулярное выражение? Какая будет регулярная грамматика для него?

Yareg ★★★ ()
Ответ на: комментарий от arsi

>стартовый топик читал, нет?

Бывают случаи некорректного ввода. Например тег из 2 слов. И даже корректная строка вида «*tag1 *tag2 *tag3 More text *not_a_tag...» Будет обработана неправильно. В «more text» не запрещены строки вида «*not_a_tag», например «2 *3=6», так что я бы не стал использовать регулярку не зная на 100%, что получу именно то, что нужно, в т.ч. при возможных некорректных аргументах.

FollowTheRabbit ()
Ответ на: комментарий от FollowTheRabbit

ты зачем сам с собой споришь?

*tag1 not_a_tag *tag2 *tag3 More text...

это будет «*tag1 More text...», потому, что

В «more text» не запрещены строки вида «*not_a_tag»

или и правда стартовый топик не читал?

arsi ★★★★★ ()
Ответ на: комментарий от Apkawa

Проблема не в этом. На регулярных выражениях невозможно сказать «делай что-то, пока не...», т.е. грубо говоря, сделать рекурсию или цикл с неизвестным заранее числом повторений. Для такой задачи надо комбинировать что-то вроде:
1. Разбить строку на tag1 и остаток
2. В остатке искать tag2
...
пока не закончится список тегов.

как только закончился, в ответе список тегов + остаток, не содержащий ни одного из них.

annoynimous ★★★★★ ()
Ответ на: комментарий от annoynimous

Кстати, в своем первом совете я был не прав. Тебе нужен не yacc/bison, в (f)lex — генератор лексических анализаторов. Он как раз и занимается тем, что генерирует список лексемм из заданной строки.

annoynimous ★★★★★ ()

Используй регулярки из .net/mono, они могут показать все совпадения из повторяющихся групп

Uter ()

А вообще, если хочешь разобраться, почитай Дж. Фридла «Регулярные выражения»

Uter ()
Ответ на: комментарий от Uter

> Используй регулярки из .net/mono, они могут показать все совпадения из повторяющихся групп

Кому нужно «показать»? Задача — разобрать строку

annoynimous ★★★★★ ()
Ответ на: комментарий от annoynimous

Всем спасибо, задача была решена вот таким способом.

Сначала извлечь строку с тегами '^\s*(?:\*\w+\s+)*'

Потом порезать строку с тегами '(?:\*([\w]+)|\S.*)'

Осталось разобраться с юникодом, но это уже другая тема.

Apkawa ()

комбинаторный парсер ftw :)

yoghurt ★★★★★ ()
Вы не можете добавлять комментарии в эту тему. Тема перемещена в архив.