Результат вложенных групп захвата

Как получить такой массив

[
    0: [ "first", "value", "1" ],
    1: [ "second", "value", "2" ],
    2: [ "third", "value", "3" ]
]

или даже лучше

[ "first", "value", "1", "second", "value", "2", "third", "value", "3" ]

из строки

"first.value[1].second.value[2].third.value[3]"

полагаться на один запуск RegEx.exec()?

Я пробовал это:

regex = /\.*([\w]+)\.([\w]+)\[([\d]*)\]/g;
var str = "first.value[1].second.value[2].third.value[3]";
result = regex.exec(str);

но я не могу получить подгруппы захвата (как в первом примере).

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


person Kamafeather    schedule 18.02.2016    source источник
comment
Используйте цикл и создайте массив динамически. Что-то вроде while ((m=regex.exec(str)) !== null) { arr.push(m[1], m[2], m[3]); ....}; См. эту демонстрацию, выдающую ["first", "value", "1", "second", "value", "2", "third", "value", "3"]   -  person Wiktor Stribiżew    schedule 18.02.2016
comment
Я знаю, что могу сделать это вручную. Но мне любопытно, как сделать то же самое с одним регулярным выражением.   -  person Kamafeather    schedule 18.02.2016
comment
Не могли бы вы уточнить часть с одним регулярным выражением? Выражение регулярного выражения не может создавать, заполнять массивы. Для этого существуют специальные языковые средства. Выражение регулярного выражения может просто соответствовать (или не соответствовать) некоторому тексту.   -  person Wiktor Stribiżew    schedule 18.02.2016
comment
Я не хотел использовать дополнительные структуры итераций и просто полагался на магию регулярных выражений! Или, по крайней мере, я хотел знать, возможно ли это. Но либо вы, либо Федерико Пьяцца (в комментарии к его ответу) ответили на мои сомнения. Тогда регулярное выражение не такое волшебство!   -  person Kamafeather    schedule 18.02.2016
comment
Это зависит от языка. В Python есть действительно крутые методы в модулях re и regex. Это просто JS, который не так волшебен с регулярными выражениями, и его методы регулярных выражений скорее вводят в заблуждение.   -  person Wiktor Stribiżew    schedule 18.02.2016


Ответы (5)


Я бы использовал split:

var str = "first.value[1].second.value[2].third.value[3]";
var res = str.split(/\]\.?|\[|\./)
person Toto    schedule 18.02.2016
comment
Можно ли получить вложенную структуру, как в первом примере? - person Kamafeather; 18.02.2016
comment
@Kamafeather: К сожалению, я не думаю, что это возможно - person Toto; 18.02.2016

Если результат редактирования - это то, что вам нужно

[ "первый", "значение", "1", "второй", "значение", "2", "третий", "значение", "3" ]

Затем вы можете использовать очень простое регулярное выражение.

/(\w+)/g

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

Вы можете использовать приведенное выше регулярное выражение (/(\w+)/g), чтобы получить массив matched, и запустить его через следующее:

var finalArr= [];

for (var i= 1, j= 0; i < matched.length; i += 3) {
  finalArr[j] = match.slice(i, 3);
  j++;
}
person GMchris    schedule 18.02.2016
comment
Можно ли получить вложенную структуру, как в первом примере? - person Kamafeather; 18.02.2016
comment
Не совсем, однако я отредактировал свой ответ, включив в него довольно простое решение, хотя, боюсь, это не только регулярное выражение. - person GMchris; 18.02.2016

Следуя вашей идее шаблона, вы можете использовать регулярное выражение следующим образом:

(.*?)\.(.*?)\[(\d+)\]\.?

Рабочая демонстрация

Информация о матче

MATCH 1
1.  [0-5]   `first`
2.  [6-11]  `value`
3.  [12-13] `1`
MATCH 2
1.  [15-21] `second`
2.  [22-27] `value`
3.  [28-29] `2`
MATCH 3
1.  [31-36] `third`
2.  [37-42] `value`
3.  [43-44] `3`
person Federico Piazza    schedule 18.02.2016
comment
Я мог бы добиться того же на regex101.com, но выполнение этого на Javascript (именно там мне нужно, чтобы он работал) с RegExp.prototype.exec() делает не возвращать этот многоуровневый массив. - person Kamafeather; 18.02.2016
comment
@Kamafeather Я сосредоточился на твоем заявлении or (even better). Вы не можете генерировать многоуровневые массивы с регулярным выражением. Regex - это просто сопоставление с образцом, если вам нужна логика, вы должны добавить в нее код. - person Federico Piazza; 18.02.2016

string.match(/(\w+)/g) Метод match для строки может создать массив, который вы ищете. Просто извлеките слова с \w:

var regex = /(\w+)/g;
var str = "first.value[1].second.value[2].third.value[3]";

var arr = str.match(regex)


document.querySelector('pre').innerHTML = JSON.stringify(arr, 0, 4);
<pre></pre>

person Jai    schedule 18.02.2016

Вы можете попробовать в 2 шага, разделить с помощью ]., а затем разделить следующий шаг, используя .

var str = "first.value[1].second.value[2].third.value[3]";
var tempArr  = (str+'.').replace(/\[/g,'.').split('].');
var finalArr = tempArr.map(function(v){return v.split('.');});

//result: [["first", "value", "1"], ["second", "value", "2"], ["third", "value", "3"], [""]]
person joyBlanks    schedule 18.02.2016