in this case I create a regex for the group in code,price,name,status but the last line does not match, I want the last line with status Y if there is no word [Y]
Harga:
X25=2.335NAME1 25 [X];
X1=5.720NAME2 5 [Y];
X2=10.720NAME3 10 [Y];
X4=4.200NAME4 4;
(?<code>.*)\=(?<price>[0-9]{1,3}\.?[0-9]{1,3})(?<name>.*)\s(?:\[(?<status>X|Y)\])
CodePudding user response:
You can change the first .*
to a negated character class matching any char except =
The name group can be changed to a negated character class matching any char other than [
and ]
Using [0-9]{1,3}\.?[0-9]{1,3}
matches at least 2 digits. If you also want to match a single digits, you can make the .
and the next 1-3 digits optional
The last part can be made optional including the whitespace char to also match the last line
(?<code>[^=\n]*)=(?<price>[0-9]{1,3}(?:\.[0-9]{1,3})?)(?<name>[^\][]*?)(?:\s*\[(?<status>[XY])\])?;
The pattern matches:
(?<code>[^=\n]*)=
Group code match optional chars other than=
, then match=
(?<price>
Group price[0-9]{1,3}(?:\.[0-9]{1,3})?
Match 1-3 digits and optionally.
and 1-3 digits
)
Close gropu(?<name>[^\][]*?)
Group name, optionally match any char except[
and]
as least as possible(?:
Non capture group to make the whole part optional\s*\[(?<status>[XY])\]
Optionally match whitespace chars, group status matching eitherX
orY
using a character class between square brackets
)?;
Close the non capture group, and match the;
at the end
If the ;
at the end is not mandatory, but it can not occur in between as well, you can exclude matching it as in this regex demo.
const regex = /(?<code>[^=\n]*)=(?<price>[0-9]{1,3}(?:\.[0-9]{1,3})?)(?<name>[^\][]*?)(?:\s*\[(?<status>[XY])\])?;/g;
const str = `Harga:
X25=2.335NAME1 25 [X];
X1=5.720NAME2 5 [Y];
X2=10.720NAME3 10 [Y];
X4=4.200NAME4 4;`;
let m;
console.log([...str.matchAll(regex)].map(m => m.groups));
<iframe name="sif1" sandbox="allow-forms allow-modals allow-scripts" frameborder="0"></iframe>