Попытка сопоставить все регулярные выражения в строке JavaScript - PullRequest
1 голос
/ 17 июня 2019

Я пытаюсь string.matchAll следующую строку:

const text = 'textA [aaa](bbb) textB [ccc](ddd) textC'

Я хочу сопоставить следующее:

  • 1st: "textA [aaa](bbb)"
  • 2-й: " textB [ccc](ddd)"
  • 3-й: " textC"

ПРИМЕЧАНИЕ: Группы захвата уже присутствуют в regex.Это то, что мне нужно.

Это почти работает, но до сих пор я не мог придумать, как сопоставить последнюю часть строки, которая является просто " textC", и не имеет [*](*) pattern.

Что я делаю не так?

const text = 'textA [aaa](bbb) textB [ccc](ddd) textC'
const regexp = /(.*?)\[(.+?)\]\((.+?)\)/g;

const array = Array.from(text.matchAll(regexp));
console.log(JSON.stringify(array[0][0]));
console.log(JSON.stringify(array[1][0]));
console.log(JSON.stringify(array[2][0]));

ОБНОВЛЕНИЕ:

Помимо хороших решений, представленных в ответах ниже, это также вариант:

const text= 'textA [aaa](bbb) textB [ccc](ddd) textC'

const regexp = /(?!$)([^[]*)(?:\[(.*?)\]\((.*?)\))?/gm;

const array = Array.from(text.matchAll(regexp));

console.log(array);

Ответы [ 3 ]

3 голосов
/ 17 июня 2019

Это потому что третьего матча нет.После первых двух совпадений в строке остается только «текст C»:

https://regex101.com/r/H9Kn0G/1/

, чтобы исправить это, сделайте всю вторую часть необязательной (также обратите внимание на начальную \w вместо ., чтобы эта точка не съела всю строку, а также символы «только для группировки», используемые для окружения необязательной части, что позволяет сохранить группы совпадений одинаковыми):

(\w+)(?:\s\[(.+?)\]\((.+?)\))?

https://regex101.com/r/Smo1y1/2/

2 голосов
/ 17 июня 2019

Решение 1: Разделение по совпадению

Вы можете разделить, сопоставив образец и получив подстроки из предыдущего индекса до конца соответствия:

const text = 'textA [aaa](bbb) textB [ccc](ddd) textC'
const regexp = /\[[^\][]*\]\([^()]*\)/g;
let m, idx = 0, result=[];
while(m=regexp.exec(text)) {
  result.push(text.substring(idx, m.index + m[0].length).trim());
  idx = m.index + m[0].length;
}
if (idx < text.length) {
  result.push(text.substring(idx, text.length).trim())
}
console.log(result);

Примечание:

  • \[[^\][]*\]\([^()]*\) соответствует [, любые 0+ символов кроме [ и ][^\][]*), затем ](, затем 0+ символов, отличных от ( и )[^()]*), а затем ) (см. regex demo )
  • Группы захвата удаляются, но вы можете восстановить их и при необходимости сохранить в результирующем массиве (или в другом массиве)
  • .trim() добавлено, чтобы избавиться отначальные / конечные пробелы (удаляйте, если не нужно).

Решение 2. Соответствие необязательному шаблону

Идея состоит в том, чтобы сопоставить любые символы перед имеющимся шаблоном, а затем сопоставить любой из них.или конец строки:

let result = text.match(/(?!$)(.*?)(?:\[(.*?)\]\((.*?)\)|$)/g);

Если строка может иметь разрывы строк, замените . на [\s\S] или рассмотрите этот шаблон:

let result = text.match(/(?!$)([\s\S]*?)(?:\[([^\][]*)\]\(([^()]*)\)|$)/g);

См. regex demo .

JS demo:

const text = 'textA [aaa](bbb) textB [ccc](ddd) textC'
const regexp = /(?!$)(.*?)(?:\[(.*?)\]\((.*?)\)|$)/g;

const array = Array.from(text.matchAll(regexp));
console.log(JSON.stringify(array[0][0]));
console.log(JSON.stringify(array[1][0]));
console.log(JSON.stringify(array[2][0]));

Regex детали

  • (?!$) - не в конце строки
  • (.*?) - Группа 1: любые 0+ символов, кроме символов разрыва строки, как можно меньше (измените на [\s\S]*?, если возможны разрывы строк, или добавьте модификатор s, так как вы нацелены на ECMAScript 2018)
  • (?:\[(.*?)\]\((.*?)\)|$) - любой из двух вариантов:
    • \[(.*?)\]\((.*?)\) - [, группа 2: любые 0+ символов, кроме символов перевода строки, как можно меньше, ](, группа 3: любые 0+ символовкроме символов перевода строки как можно меньше, и )
    • | - или
    • $ - конец строки.
0 голосов
/ 20 июня 2019

Вот что я использовал в итоге:

const text= 'textA [aaa](bbb) textB [ccc](ddd) textC'

const regexp = /(?!$)([^[]*)(?:\[(.*?)\]\((.*?)\))?/gm;

const array = Array.from(text.matchAll(regexp));

console.log(array);
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...