Вытащить из строчки некоторые параметры

URL.match(/(?<=(auto|news)-|[?&]mdl=)\d+/g)?.map(v => +v)

Вытаскиваем число что после дефиса и число при наличии Гет параметра mdl. Сразу преобразовываем значения как числовые...

Как сделать так, чтобы на выходе в массиве, появилось еще значение. Строковое, вытащить то что до дефиса. То есть либо auto либо news...

Примеры строк

https://example.com/auto-123?mdl=789
https://example.com/news-123
https://example.com/auto-123?asd=22&mdl=789
https://example.com/mmm-123

Если в строчке нет ни 'auto' ни 'news'. Необходимо вернуть NULL. Первое значение в массиве всегда должно быть 'auto' ни 'news', второе '123', а третье его может не быть это значение mdl


Ответы (2 шт):

Автор решения: Uranus

Для того чтобы получить и числовое значение после дефиса, и строку, которая находится перед ним (auto или news), лучше использовать не ретроспективные проверки а несколько скобочных групп, чтобы извлекать оба значения.

const URL = "https://example.com/page?auto-123&news-456&mdl=789";

const matches = Array.from(
  URL.matchAll(/(auto|news)-(\d+)|[?&]mdl=(\d+)/g),
  match => ({
    type: match[1] || 'mdl', // либо 'auto', 'news', либо 'mdl'
    value: +(match[2] || match[3]) // числовое значение после дефиса или значение mdl
  })
);

console.log(matches);

→ Ссылка
Автор решения: stylok

С учетом появившихся примеров строк для разбора, сразу стало как-то легче. Давайте по порядку. Во-первых нет смысла подстраиваться под и без того не самую внятную для понимания регулярку. Тем более что нам нужно больше данных, а потому напишем свою. И с места в карьер...

/(((auto|news)-\d+)|(mdl=\d+))/g

Если присмотреться, то всё вполне понятно "скобочные группы", "или" и "цифры" (от одной и более), которые благодаря .match() вернёт нам массив значений в виде массива — ['auto-123', 'mdl=789'].

И нам останется лишь вытянуть нужные параметры и их значения. Не знаю в каком окончательном виде они вам больше нравятся, но предположу, что в виде объекта. Однако для простоты понимания я для начала приведу результат в виде результатов match(), потом пройдёмся .map() для наглядности, и в конце вероятно нужным вам .reduce(), чтобы результат был в виде объекта.

const arr = [
  'https://example.com/auto-321?mdl=789',
  'https://example.com/news-123',
  'https://example.com/auto-123?asd=22&mdl=789',
]
arr.forEach(url => {
  const data = url.match(/(((auto|news)-\d+)|(mdl=\d+))/g)
  console.log(data)
});

Думаю достаточно наглядно получилось. Собственно всё что нам остаётся, так это превратить их в массив или объект при помощи .split()

.split(/\-|=/) // по регулярке ибо у нас есть выбор между 'минус' и 'равно'

const arr = [
  'https://example.com/auto-321?mdl=789',
  'https://example.com/news-123',
  'https://example.com/auto-123?asd=22&mdl=789',
]
arr.forEach(url => {
  const data = url.match(/(((auto|news)-\d+)|(mdl=\d+))/g).map(i =>  i.split(/\-|=/))
  console.log(data)
});

Как видите у нас появился массив вида ['ключ','значение'] и всё что нам остаётся так это вернуть результат в том или ином виде. Способов достаточно, но коль мы уже воспользовались .map() то вернём массив объектов.

const arr = [
  'https://example.com/auto-321?mdl=789',
  'https://example.com/news-123',
  'https://example.com/auto-123?asd=22&mdl=789',
]
arr.forEach(url => {
  const data = url.match(/(((auto|news)-\d+)|(mdl=\d+))/g).map(i => {
    const re = i.split(/\-|=/)
    return {[re[0]]: re[1]} // [re[0]] — небольшое "колдунство" для получения имени ключа
  });
  console.log(data)
});

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

const arr = [
  'https://example.com/auto-321?mdl=789',
  'https://example.com/news-123',
  'https://example.com/auto-123?asd=22&mdl=789',
]
arr.forEach(url => {
  const data = url.match(/(((auto|news)-\d+)|(mdl=\d+))/g)  .reduce((acc,i) => {
    const re = i.split(/\-|=/)
    acc[re[0]] = re[1];
    return acc
  }, {});
  console.log(data)
});

Собственно всё что вам нужно, так это

URL?.match(/(((auto|news)-\d+)|(mdl=\d+))/g).reduce((acc,i) => {
  const re = i.split(/\-|=/)
  acc[re[0]] = re[1];
  return acc
}, {});

P.S. возможно вы заметили, что я убрал из массива заведомо "невалидную" строку... это только по причине, чтобы не мусорить в примерах "условностями", но в вашем случае всё уже предусмотрено благодаря ?.URL?.match().

P.P.S. для освоения регулярки и прочих тренировок по этой части консоль не всегда удобна, но есть онлайн сервисы на выбор тыц или тыц.

→ Ссылка