Reputation: 3198
I want to validate a range using javascript
Any range that has $ symbol must say invalid
Any range string that has symbols other than : must say invalid
Accpetable characters are capital or small alphabets and 0-9 numbers
Some of the expected results
A0 // invalid range begins with 1
ZZ12 // valid
ZZ12: // invalid incorrectly terminated
:A11 // invalid incorrectly started
:1 // invalid incorrectly started
:A // invalid incorrectly started
A1 // valid
B1 // valid
A2 // valid
C:F // valid
A10:B10 // valid
A:B10 // valid
A10:B // valid
A:B // valid
10:10 // valid
AA1 // valid
AAA1 // valid
B9:B10 // valid
A // invalid incomplete range string
1 // invalid incomplete range string
B // invalid incomplete range string
20 // invalid only a number not allowed
@ // invalid symbols not allowed
## // invalid symbols not allowed
I have tried with
["A0","ZZ12","ZZ12:",":A11",":1",":A","A1","B1","A2","C:F","A10:B10","A:B10","A10:B","A:B","10:10","AA1","AAA1","B9:B10","A","1","B","20","@","##"]
.map(zz=>{return zz + "--->" + /^[A-Z]?[0-9]?:[A-Z]?[0-9]?$/.test(zz)})
Upvotes: 2
Views: 151
Reputation: 133760
With your shown samples please try following regex and JS code. Here is the Online Demo for used regex.
const regex = /^(?:[a-zA-Z]+\d*:[a-zA-Z]+\d*|[a-zA-Z]+[1-9]+\d*|\d+:\d+)$/;
[
"A0",
"ZZ12",
"ZZ12:",
":A11",
":1",
":A",
"A1",
"B1",
"A2",
"C:F",
"A10:B10",
"A:B10",
"A10:B",
"A:B",
"10:10",
"AA1",
"AAA1",
"B9:B10",
"A",
"1",
"B",
"20",
"@",
"##",
"$"
].forEach(element =>
console.log(`${element} ----> ${regex.test(element)}`)
);
Explanation: Adding detailed explanation for above used regex.
^ ##Checking from starting of value here.
(?: ##Starting one and only non-capturing group here.
[a-zA-Z]+\d*: ##matching 1 or more alphabets followed by 0 or more digits followed by colon.
[a-zA-Z]+\d* ##matching 1 or more alphabets followed by 0 or more digits here.
| ##Putting OR condition here.
[a-zA-Z]+[1-9]+\d* ##Matching 1 or more alphabets followed by 1 or more digits.
| ##Putting OR condition here.
\d+:\d+ ##Matching 1 or more digits followed by colon followed by 1 or more digits.
)$ ##Closing non-capturing group at the end of the value here.
Upvotes: 3
Reputation: 1086
Try this:
^([A-Za-z])\1*(?:[1-9]\d*)*:([A-Za-z])\2*(?:[1-9]\d*)*$|^(?:([A-Za-z])\3*|[1-9]\d*:)[1-9]\d*$
Explanation:
First part
^([A-Za-z])\1*(?:[1-9]\d*)*:([A-Za-z])\2*(?:[1-9]\d*)*$
to match things likeC:F
,A10:B10
,A:B10
,A10:B
,A:B
andB9:B10
.
^
start of the line/string.
([A-Za-z])
Group1: [A-Za-z]
one letter captured by the first group, and the value inside the first capturing group can be accessed by \1
.
\1*
, \1
the value inside the first capturing group, *
match zero or more of the value inside the first capturing group, for example if the value is A
, then things like AAA
will be matched.
(?:[1-9]\d*)*
non-capturing group, [1-9]
one digit from 1
to 9
, followed by \d*
zero or more digits from 0
to 9
, and that group will be repeated between zero or more times.
:
a literal colon :
.
([A-Za-z])
Group2:[A-Za-z]
the same as before with Group1, but now we can access the value inside the second capturing group by \2
.
\2*
the same as before with \1*
, but now the value is the one inside the second capturing group.
(?:[1-9]\d*)*
the same as before.
$
the end of the line/string.
|
the alternation operator it is like Boolean OR
, to match other cases.
Second part
^(?:([A-Za-z])\3*|[1-9]\d*:)[1-9]\d*$
to match things likeA1
,B1
,A2
and10:10
.
^
the start of the line/string.
(?:([A-Za-z])\3*|[1-9]\d*:)
non-capturing group contains:
([A-Za-z])
Group3:[A-Za-z]
the same as before with Group1 and Group2, but now we can access the value inside the third capturing group by \3
.\3*
the same as before with \1*
and \2*
, but now the value is the one inside the third capturing group.|
the alternation operator it is like Boolean OR
, to match other cases.[1-9]\d*:
one digit from 1
to 9
, followed by zero or more digits from 0
to 9
, followed by a literal :
.[1-9]\d*
one digit from 1
to 9
, followed by zero or more digits from 0
to 9
.
$
the end of the line/string.
See regex demo
Upvotes: 2
Reputation: 7616
This solution should address all your requirements, also for non-zero numbers:
const regex = /^(?:[A-Z]+[1-9][0-9]*|[A-Z]+(?:[1-9][0-9]*)?:[A-Z]+(?:[1-9][0-9]*)?|[1-9][0-9]*:[1-9][0-9]*)$/;
["A0","ZZ12","ZZ12:",":A11",":1",":A","A1","B1","A2","C:F","A10:B10","A:B10","A10:B","A:B","10:10","1:999","0:1","AA1","AAA1","B9:B10","A","1","B","20","@","##"
].map(str => {
//let valid = regex.test(str);
let valid = str.match(regex);
console.log(str, '==>', valid ? 'ok' : 'invalid');
});
Explanation of regex:
^(?:
-- start of string and non-capture group start
[A-Z]+[1-9][0-9]*
-- 1+ letters, number starting from 1|
-- logical or
[A-Z]+(?:[1-9][0-9]*)?:[A-Z]+(?:[1-9][0-9]*)?
-- 1+ letters, optional number starting from 1, :
, 1+ letters, optional number starting from 1|
-- logical or
[1-9][0-9]*:[1-9][0-9]*
-- 1+ letters, number starting from 1, :
, 1+ letters, number starting from 1)$
-- end of non-capture group and stringUpvotes: 4