Reputation: 3894
Im having trouble with a simple regex expression.
Lets say i have the following templates:
PWR_{state}
VOL_{region}_{level}
CHANEL_<key:1>_..._<key:n>
My data looks like this:
PWR_ON
/ PWR_OFF
VOL_MASTER_21
VOL_SECOND_76
CHANEL_<key:1>_..._<key:n>
All i want is a object that maps the template to the values:
PWR_ON
:
{
"state": "ON", // "OFF"
}
VOL_SECOND_76
:
{
"region": "SECOND",
"level": "76"
}
How can this elegent be archived ? What i tried till now:
const CMD = "VOL_SECOND_21";
const TEMPLATE = "VOL_{region}_{level}";
// get parameter key name from template
//const names = /{(.+?)}/g.exec(cmd_obj.template);
const names = new RegExp("{(.+?)}", "gm").exec(TEMPLATE).slice(1);
// get values for parameter keys
const regex = TEMPLATE.replace(/{.+?}/g, "(.*)");
const values = new RegExp(regex, "g").exec(CMD).slice(1);
// key/value missmatch
// ["region", <level>] ["SECOND", "21"]
console.log(names, values)
The problem here is that only the first {key}
gets matched, the rest is ignored and i dont know why.
And then i need a sexy way to create my object...
I have that feeling that can be done more easier what i try.
Upvotes: 1
Views: 526
Reputation: 192422
The RegExp.exec()
method works by finding a match, and updating the RegExp object, with the currently found index. Then you need to call exec again with the same RegExp object, you'll get the next match and so on.
Since you're calling the TEMPLATE
exec only once with a single expression you get the 1st match.
CMD exec works because the expression can match everything you're looking for.
Instead of exec you can use String.match()
, and create an expression that will catch all the relevant groups.
To create the object, map the names and the values to pairs, and use Object.fromEntries()
to get a new object.
const CMD = "VOL_SECOND_21";
const TEMPLATE = "VOL_{region}_{level}";
const names = TEMPLATE.match(/[^\{\}]+(?=\})/g);
const regex = TEMPLATE.replace(/{.+?}/g, "(.*)");
const values = CMD.match(new RegExp(regex)).slice(1);
const result = Object.fromEntries(names.map((s, i) => [s, values[i]]))
console.log(result)
Upvotes: 2