Вытащить из строчки некоторые параметры
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 шт):
Для того чтобы получить и числовое значение после дефиса, и строку, которая находится перед ним (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);
С учетом появившихся примеров строк для разбора, сразу стало как-то легче. Давайте по порядку. Во-первых нет смысла подстраиваться под и без того не самую внятную для понимания регулярку. Тем более что нам нужно больше данных, а потому напишем свою. И с места в карьер...
/(((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. для освоения регулярки и прочих тренировок по этой части консоль не всегда удобна, но есть онлайн сервисы на выбор тыц или тыц.