I'm trying to make sure only one type of special character (semi-colon, comma, or space) is used in a string.
Valid case:
- Can contain alphanumeric letters and numbers
- Can contain special characters : / .
- Can contain only one type of special characters from: space, semi-colon or comma in the string
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)
CodePudding user response:
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 string
See 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.
CodePudding user response:
Is only one
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;
}