Javascript-форум (https://javascript.ru/forum/)
-   Общие вопросы Javascript (https://javascript.ru/forum/misc/)
-   -   позиция подмасок в в регулярном выражении (https://javascript.ru/forum/misc/36924-poziciya-podmasok-v-v-regulyarnom-vyrazhenii.html)

edison 01.04.2013 14:44

позиция подмасок в в регулярном выражении
 
пишу конструктор регулярных выражений, есть желание в нем сделать подсветку найденных групп в исходном тексте.
пример - исходный текст:

xxab
aaaa
aaaa
bbbb
baxt

регулярка

/aaa(a)\na(a)aa\nbb(b)/

как найти позиции найденных групп?

чтобы я мог пометить их

xxab
aaaa
aaaa
bbbb
baxt

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

Aetae 01.04.2013 22:41

В нэте полно online regexp тестеров. Посмотрите как оные устроены.

edison 02.04.2013 03:04

Смотрел несколько десятков онлайн конструкторов, не нашел чтобы подсвечивало подгруппы. Или всё совпадение подсвечивает или текстом выдает результат.
Нашел такое решение:
var m= /(s+)(.*?)(l)([^l]*?)(o+)/.exec('this is hello to you');
function indexOfGroup(match, n) {
    var ix= match.index;
    for (var i= 1; i<n; i++)
        ix+= match[i].length;
    return ix;
}

alert(indexOfGroup(m, 3));

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

Пока думаю остановится на варианте с использованием ajax+php (preg_match PREG_OFFSET_CAPTURE) но постоянно отправлять на сервер запросы не есть гуд.

Aetae 02.04.2013 03:25

А никто не говорил, что будет легко.)
Я так понял у вас должна быть работа не с regexp js, а regexp как таковыми и в этом вся сложность. Возможно вам поможет эта вещица.

rgl 02.04.2013 12:07

edison,
Сложение матчей не дает в результате исходную строку. Допустим, в регулярке есть вложенные скобки, или же скобки со звездой после. Что будет в этом случае? Ну, напр. строка "abcd1d2d3efg" и регулярка /(d\d)*/

megaupload 02.04.2013 12:25

Цитата:

Сообщение от edison
пишу конструктор регулярных выражений

а зачем? (вопрос не риторический, если ты обучаешься то подскажу)

edison 03.04.2013 18:25

Aetae
Не нашел по ссылке решение задачи, только нашел поиск с опр позиции, а вот позиции подмасок не увидел. Еще там были примеры с index и lastIndex но это позиции вхождения всего шаблона.
rgl
Да я это написал, что если группа в группе, то будут сложности. Ну в теории можно вкладывать такие группы в другую группу, подсчитывать количество символов выкидывать ненужные значения и т.д. и т.п. в общем там кода будет на целый проект)
megaupload
Нет не обучаюсь, пишу под себя так как приходится много регехп составлять и необходим свой инструмент со своими нюансами в реализации от вставки текста из базы и подсчета количества символов, до автоматической замены некоторых участков в самой регулярке.

Остановлюсь тогда на связке ajax+php, спасибо что подумали со.

rgl 03.04.2013 18:38

Хорошая программка, и группы подсвечивает (не онлайн)
http://www.regexbuddy.com/screens/debug.png

edison 04.04.2013 00:30

rgl Спасибо, но я наверное не в полной мере объяснил что именно хочу сделать.
конструктор уже написан, там нету только подсветки групп. Конструктор является небольшой частью всего функционала. Переносить весь функционал на другой яп будет очень проблематично, сейчас основаня часть это php+js из которого только JS на 500 кб (я говорю о всем функционале, а не только о конструкторе regexp). А так как я изучаю языки всего то около года. То я подумал, что возможно, где-то что-то упустил в мануалах и есть возможность выводить позиции матчей, например как это сделано в пхп. У меня сейчас только 3 выхода, это переписывать полностью клиенскую часть на С, найти возможность реализовать поиск позиции на JS или отправлять регехп в другую среду и получать оттуда уже ответ с позициями. В принципе не очень важная функция и сэкономит мне несколько секунд времени на составление 1 регехп, но из мелочей так и получается ощутимая экономия (до этого вообще приходилось вручную перебирать пару десятков регулярок и пробовать их обрезать, сейчас помогает конструктор и на автомате подставляет уже составленные регулярки и пробует их переделать под исходный текст). Пока пришел к выводу что для меня сейчас рациональнее сделать ajax+php потом попробую почитать мануалы по java,flash возможно там есть нужный мне функционал, чтобы сделать его на клиентской части, а не отправлять постоянно данные на сервер.

nerv_ 05.04.2013 11:22

Цитата:

Сообщение от edison
как найти позиции найденных групп?

alert( 'some text bla bla bla text la la la'.replace( /t(ext)/g, function( a, b ) { return '#' + b + '#';}) );

rgl 05.04.2013 12:11

nerv_,
А где тут позиции?
(т.е. где число?)

nerv_ 05.04.2013 12:43

Цитата:

Сообщение от rgl
А где тут позиции?

во-первых, нафига они нужны, если требуется
Цитата:

Сообщение от edison
сделать подсветку найденных групп

во-вторых
function( a, b, c ) { // с - позиция a

rgl 05.04.2013 13:33

Цитата:

Сообщение от nerv_ (Сообщение 244379)
во-первых, нафига они нужны,

во-вторых
function( a, b, c ) { // с - позиция a

Во-первых, как подсветить, не зная что нужно подсвечивать?
во-вторых, c - позиция всего выражения, а не группы.

nerv_ 05.04.2013 16:26

Цитата:

Сообщение от rgl
как подсветить, не зная что нужно подсвечивать

первый пост почитай
Цитата:

Сообщение от edison
сделать подсветку найденных групп в исходном тексте


Цитата:

Сообщение от rgl
c - позиция всего выражения, а не группы

о чем я написал постом выше

rgl 05.04.2013 17:30

Цитата:

Сообщение от nerv_ (Сообщение 244425)
первый пост почитай

Читаю:
Цитата:

Сообщение от nerv_ (Сообщение 244359)
alert( 'some text bla bla bla text la la la'.replace( /t(ext)/g, function( a, b ) { return '#' + b + '#';}) );

и вижу, что получается не то. Ну, напр. сделаем так:

alert( 'CLEAR="left" causes the next text line to start down as soon as the left margin is clear'.replace( /next t(ext)/g, function( a, b ) { return '#' + b + '#';}) );


Получается не
CLEAR="left" causes the next t#ext# line to start down as soon as the left margin is clear
а
CLEAR="left" causes the #ext# line to start down as soon as the left margin is clear

Aetae 05.04.2013 23:11

Тут это сделано, код не обсфуцирован - бери да пользуйся.

edison 07.04.2013 02:16

Цитата:

Сообщение от Aetae (Сообщение 244474)
бери да пользуйся.

Спасибо, но там выделяет не именно те матчи которые совпали, а идет реплейс
^(.*?)match1(.*?)match2(.*?)match3(.*?)$
на
$1<span class="group-1">match1</span>$2<span class="group-2">match2</span>$3<span class="group-3">match3</span>$4

соответственно это не точные позиции матчей.
Я примерно такое-же делал, только я сдвигал позицию под каждое совпадение, чтобы они были последовательно подсвечены.

Если ввести там регексп из моего первого сообщения то на выходе будет
xxab
aaaa
aaaa
bbbb
baxt

ну и группа в группе тоже сдвинет весь результат
(aaa(a))\na(a)aa\nbb(b)

xxab
aaaa
aaaa
bbbb
baxt

nerv_ заменяется ведь все вхождение регексп, вот если бы только подгруппы можно было заменить.

мысль только распарсить регулярку поочередно закрывая все группы (?:) кроме одной и по бокам этой группы заключать в скобки части регулярки.


допустим имеем
(aaa(a))\na(a)*aa\nbb(b)
преобразуем
(aaa(?:a))(\na(?:a)*aa\nbb(?:b)) т.к. первая группа начинается с самого вхождения, то выйдет всего 2 группы, тоже самое если мы работаем с последней группой и регексп заканчивается ей

получаем

aaaa

и

aaaa
bbbb

получаем начальную позицию длина pos=матч1+index
высчитываем позицию окончания
poslast=матч0-(матч1+матч3), тем самым мы высчитаем длину матча (a)* - когда группа повторяется или poslast=длинна совпадения+матч0-(матч1+матч2+матч3) в зависимости от того будем мы захватывать *?+ и т.д. после группы те. будет у нас так (a)* или мы преобразуем группу в ((?:a)*)

итого на выходе мы будем иметь позицию и длину вхождения

второе преобразование соответственно такое

(?:(aaa)(a))(\na(?:a)*aa\nbb(?:b))

((?:aaa(?:a))\na)(a)*(aa\nbb(?:b))

и т.д.

сложность в том, что нужно будет распаршивать регулярку по группам и закрывать группы. Кода возможно и не так много получится, но придется поломать голову над точным вычленением каждой подгруппы и позиций для образования новых подгрупп.

поправлюсь, количество новых групп не будет ограничено от 2 до 3, а будет расширятся если у нас подгруппа для которой мы находим позицию находится в другой подгруппе (-ах) т.е s(aaa(a)s)x - получится нужно проставить еще 4 подгруппы (s)(?:(aaa)(a)(s))(x) и чем больше вложений тем больше подгрупп будет

В общем изврат)) Возможно кому-то пригодится для дальнейших раздумий, но писать такой велосипед...

nerv_ 09.04.2013 01:03

Цитата:

Сообщение от edison
nerv_ заменяется ведь все вхождение регексп, вот если бы только подгруппы можно было заменить

alert( 'some text bla bla bla text la la la'.replace( /(t)(ext)/g, function( a, b, c ) { return b+ '#' + c + '#';}) );

или переписывать регу

Цитата:

Сообщение от rgl
и вижу, что получается не то

ну а додумать?) не? :)

Aetae 09.04.2013 01:07

Цитата:

Сообщение от nerv_ (Сообщение 244935)
ну а додумать?) не? :)

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

nerv_ 09.04.2013 01:15

Цитата:

Сообщение от Aetae
функция должна работать с произвольной.

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

Я ток седня закончил составлять регулярку в многобукв. Вытаскивает из текста числа прописью и переводит их в числа: одиннадцать целых две сотых -> 11.02

Aetae 09.04.2013 01:44

Цитата:

Сообщение от nerv_ (Сообщение 244938)
с чем бы она не работала, как правило, всегда есть от чего оттолкнуться. Если нет, то нет смысла писать код, тем более реги.

Я ток седня закончил составлять регулярку в многобукв. Вытаскивает из текста числа прописью и переводит их в числа: одиннадцать целых две сотых -> 11.02

Это не особо сложно, а вот предусмотреть бесконечную вложенность в данном примере посложнее.)


Часовой пояс GMT +3, время: 20:46.