Reputation: 47
I'm trying to make sure only one type of special character (semi-colon, comma, or space) is used in a string.
Valid case:
e.g this should match as it only uses one type of special character (semi-colon): https://hello.com/example1;https://hello.com.com/example2;https://hello.com.com/example3
This should fail as it mixes two types of special characters (space and semi-colon)
https://hello.com/example1; https://hello.com.com/example2 ;https://hello.com.com/example3
This is my code:
const myValidation = yup
.string()
.matches(/^([A-Za-z0-9://,\\.]|[A-Za-z0-9:// \\.]|[A-Za-z0-9://;\\.])+$/, 'Please separate each with a comma, space or semicolon')
.required();
When i only have /^([A-Za-z0-9://,\\.]+$/
it works correctly to only match the string if it has a only a comma as special character:
https://hello.com/example1,https://hello.com.com/example2,https://hello.com.com/example3
but as soon as i add the other or conditions /^([A-Za-z0-9://,\\.]|[A-Za-z0-9:// \\.]|[A-Za-z0-9://;\\.])+$/
it starts allowing for semi-colon and space and comma special characters in the string at the same time (the invalid case)
Upvotes: 0
Views: 1201
Reputation: 64040
function isOnlyOne() {
let s = "zy,,aemnofgbcjkhilpqasdfrstuvrhfwx";
console.log([...new Set(s.split("").filter(e => e.match(/[;, ]/)))].length==1);
//return [...new Set(s.split("").filter(e => e.match(/[a-z]/)))].length==26;
}
Upvotes: 0
Reputation: 163267
For the valid cases, you can use a capture group with a backreference \1
to make sure that the "special character" is the same delimiter between the matches
^[A-Za-z0-9:/.]+(?:([ ,;])[A-Za-z0-9:/.]+(?:\1[A-Za-z0-9:/.]+)*)?$
The pattern matches:
^
Start of string[A-Za-z0-9:/.]+
Match 1+ of the allowed characters(?:
Non capture group to match as a whole part
([ ,;])
Capture group 1, match one of the delimiters[A-Za-z0-9:/.]+
Match 1+ of the allowed characters(?:\1[A-Za-z0-9:/.]+)*
Optionally repeat a backreference to the same delimiter and again 1+ of the allowed characters)?
Close the non capture group and make it optional$
End of stringSee a regex demo.
const regex = /^[A-Za-z0-9:/.]+(?:([ ,;])[A-Za-z0-9:/.]+(?:\1[A-Za-z0-9:/.]+)*)?$/;
[
"https://hello.com/example1;https://hello.com.com/example2;https://hello.com.com/example3",
"https://hello.com/example1; https://hello.com.com/example2 ;https://hello.com.com/example3",
"https://hello.com/example1"
].forEach(s =>
console.log(`${regex.test(s)} --> ${s}`)
);
If there should be at least a single delimiter present, you could shorten the pattern to:
^[A-Za-z0-9:/.]+([ ,;])[A-Za-z0-9:/.]+(?:\1[A-Za-z0-9:/.]+)*$
If the strings should start with http://
or https://
you could use:
^https?:\/\/[A-Za-z0-9:/.]+(?:([ ,;])https?:\/\/[A-Za-z0-9:/.]+(?:\1[A-Za-z0-9:/.]+)*)?$
See another regex demo.
Upvotes: 1