dagda1
dagda1

Reputation: 28898

Reuse capturing group pattern in JS regex

I want to test whether a string is 8 digits or the same number can be divided into 4 parts separated by a -.

I have a regex that does work:

/^\d{2}([-]?)(\d{2})\1\d{2}\1\d{2}$/

And I can prove:

/^\d{2}([-]?)(\d{2})\1\d{2}\1\d{2}$/.test('12345678'); // true
/^\d{2}([-]?)(\d{2})\1\d{2}\1\d{2}$/.test('12-34-56-78');  // true
/^\d{2}([-]?)(\d{2})\1\d{2}\1\d{2}$/.test('12-45-7810'); // false
/^\d{2}([-]?)(\d{2})\1\d{2}\1\d{2}$/.text('-12-45-78-10'); //false

I would have liked to have created a group from \d{2} but I tried this:

/^(\d{2})([-]?)\1\2\1\2\1$/

But it does not match anything.

Upvotes: 1

Views: 2869

Answers (3)

Wiktor Stribiżew
Wiktor Stribiżew

Reputation: 627410

You cannot make backrefernces (references to actual values captured with group patterns) work as subroutines (constructs "repeating" some group patterns, not the actual captured values).

You can only define pattern parts and use them to build longer patterns:

const n = "\\d{2}";
const h = "-?";
const rx = new RegExp(`^${n}(?:${h}${n}){3}$`);
console.log(rx.source); // ^\d{2}(?:-?\d{2}){3}$
// ES5:
// var rx = new RegExp("^" + n + "(?:" + h + n+ "){3}$");
 
const strs = ['12345678', '12-34-56-78', '12-45-7810', '-12-45-78-10'];
for (let s of strs) {
	console.log(s, "=>", rx.test(s));
}

Upvotes: 1

edmond
edmond

Reputation: 1592

Have you tried:

const r = new RegExp(/^-?\d{2}-?\d{2}-?\d{2}-?\d{2}$/);
console.log(r.test("12345678")); // true
console.log(r.test("12-34-56-78")); // true
console.log(r.test("12-45-7810")); // true
console.log(r.test("-12-45-78-10")); // true

This works on my end.

Upvotes: 0

Hegel F.
Hegel F.

Reputation: 125

You can write even shorter: ^\d\d(-\d\d){3}$|^\d{8}$

Upvotes: 1

Related Questions