Insert hyphen when regex group is not null or empty - javascript

I have a numeric code which varies in length from 6-11 digits
which is separated by hyphen after each 3 digits
possible combinations
123-456
123-456-78
123-456-7890
So, here I am trying to convert the user entered code to this format even when entered with spaces and hyphens in the middle.
For Ex:
123 456-7 -> 123-456-7
123456 789 -> 123-456-789
123456 -> 123-456
Valid user input format is 3digits[space or hyphen]3digits[space or hyphen]0to5digits
I tried it like this
code.replace(/^(\d{3})[- ]?(\d{3})[- ]?(\d{0,5})$/,'$1-$2-$3');
But when there are only 6 digits there is a hyphen(-) at the end of the number which is not desired.
123-456-
Could anybody help me with this? Thank you.

The easiest way is probably to just do this with a second replace:
code.replace(/^(\d{3})[- ]?(\d{3})[- ]?(\d{0,4})$/,'$1-$2-$3')
.replace(/-$/, '');
This is chaining a second replace function, which says "replace a - at the end of the string with an empty string". Or in other words, "if the last character of the string is - then delete it.
I find this approach more intuitive than trying to fit this logic all into a replace command, but this is also possible:
code.replace(
/^(\d{3})[- ]?(\d{3})[- ]?(\d{0,4})$/,
'$1-$2' + ($3 == null ? '' : '-') + $3
)
I think it's less obvious at a glance what this code i doing, but the net result is the same. If there was no $3 matched (i.e. your sting only contained 6 digits), then do not include the final - in the replacement.

I believe this will do it for you - replace
^(\d{3})[ -]?()|(\d{3})[ -]?(\d{1,5})
with
$1$3-$2$4
It has two alternations.
^(\d{3})[ -]?() matches start of line and then captures the first group of three digits ($1), then optionally followed by a space or an hyphen. Finally it captures an empty group ($2).
(\d{3})[ -]?(\d{1,5}) matches, and captures ($3), three digits, optionally followed by a space or an hyphen. Then it matches and captures (($4)) the remaining 1-5 digits if they're present.
Since the global flag is set it will make one or two iterations for each sequence of digits. The first will match the first alternation, capturing the first three digits into group 1. Group 2 will be empty.
For the second iteration the first match have matched the first three digits, so this time the second alternation will match and capture the next three digits into group 3 and then the remaining into group 4.
Note! If there only are three digits left after the first match, none of the alternations will match, leaving the last three digits as is.
So at the first iteration group 1 are digits 123. group 2, 3 and 4 are empty. The second iteration group 1 and two are empty, group 3 are the digits 456 and group 4 are digit 7-11.
This gives the first replace $1 = 123- plus nothing, and the second 456-67....
There's no syntax checking in this though. It assumes the digits has been entered as you stated they would.
See it here at regex101.

Related

Regex with lowercase, uppercase, alphanumeric, special characters and no more than 2 identical characters in a row with a minimum length of 8 chars [duplicate]

This question already has answers here:
Regex for password must contain at least eight characters, at least one number and both lower and uppercase letters and special characters
(42 answers)
Closed 3 years ago.
I'm trying to create a regex that allows the 4 main character types (lowercase, uppercase, alphanumeric, and special chars) with a minimum length of 8 and no more than 2 identical characters in a row.
I've tried searching for a potential solution and piecing together different regexes but no such luck! I was able to find this one on Owasp.org
^(?:(?=.*\d)(?=.*[A-Z])(?=.*[a-z])|(?=.*\d)(?=.*[^A-Za-z0-9])(?=.*[a-z])|(?=.*[^A-Za-z0-9])(?=.*[A-Z])(?=.*[a-z])|(?=.*\d)(?=.*[A-Z])(?=.*[^A-Za-z0-9]))(?!.*(.)\1{2,})[A-Za-z0-9!~<>,;:_=?*+#."&§%°()\|\[\]\-\$\^\#\/]{8,32}$
but it uses at least 3 out of the 4 different characters when I need all 4. I tried modifying it to require all 4 but I wasn't getting anywhere. If someone could please help me out I would greatly appreciate it!
Can you try the following?
var strongRegex = new RegExp("^(?=.*[a-z])(?=.*[A-Z])(?=.*[0-9])(?=.*[!##\$%\^&\*])(?=.{8,})");
Explanations
RegEx Description
(?=.*[a-z]) The string must contain at least 1 lowercase alphabetical character
(?=.*[A-Z]) The string must contain at least 1 uppercase alphabetical character
(?=.*[0-9]) The string must contain at least 1 numeric character
(?=.[!##\$%\^&]) The string must contain at least one special character, but we are escaping reserved RegEx characters to avoid conflict
(?=.{8,}) The string must be eight characters or longer
or try with
(?=.{8,100}$)(([a-z0-9])(?!\2))+$ The regex checks for lookahead and rejects if 2 chars are together
var strongerRegex = new RegExp("^(?=.*[a-z])(?=.*[A-Z])(?=.*[0-9])(?=.*[!##\$%\^&\*])(?=.{8,100}$)(([a-z0-9])(?!\2))+$");
reference
I think this might work from you (note: the approach was inspired by the solution to this SO question).
/^(?:([a-z0-9!~<>,;:_=?*+#."&§%°()|[\]$^#/-])(?!\1)){8,32}$/i
The regex basically breaks down like this:
// start the pattern at the beginning of the string
/^
// create a "non-capturing group" to run the check in groups of two
// characters
(?:
// start the capture the first character in the pair
(
// Make sure that it is *ONLY* one of the following:
// - a letter
// - a number
// - one of the following special characters:
// !~<>,;:_=?*+#."&§%°()|[\]$^#/-
[a-z0-9!~<>,;:_=?*+#."&§%°()|[\]$^#/-]
// end the capture the first character in the pair
)
// start a negative lookahead to be sure that the next character
// does not match whatever was captured by the first capture
// group
(?!\1)
// end the negative lookahead
)
// make sure that there are between 8 and 32 valid characters in the value
{8,32}
// end the pattern at the end of the string and make it case-insensitive
// with the "i" flag
$/i
You could use negative lookaheads based on contrast using a negated character class to match 0+ times not any of the listed, then match what is listed.
To match no more than 2 identical characters in a row, you could also use a negative lookahead with a capturing group and a backreference \1 to make sure there are not 3 of the same characters in a row.
^(?=[^a-z]*[a-z])(?=[^A-Z]*[A-Z])(?=[^0-9]*[0-9])(?=[^!~<>,;:_=?*+#."&§%°()|\[\]$^#\/-]*[!~<>,;:_=?*+#."&§%°()|\[\]$^#\/-])(?![a-zA-Z0-9!~<>,;:_=?*+#."&§%°()|\[\]$^#\/-]*([a-zA-Z0-9!~<>,;:_=?*+#."&§%°()|\[\]$^#\/-])\1\1)[a-zA-Z0-9!~<>,;:_=?*+#."&§%°()|\[\]$^#\/-]{8,}$
^ Start of string
(?=[^a-z]*[a-z]) Assert a-z
(?=[^A-Z]*[A-Z]) Assert A-Z
(?=[^0-9]*[0-9]) Assert 0-9
(?= Assert a char that you would consider special
[^!~<>,;:_=?*+#."&§%°()|\[\]$^#\/-]*
[!~<>,;:_=?*+#."&§%°()|\[\]$^#\/-]
)
(?! Assert not 3 times an identical char from the character class in a row
[a-zA-Z0-9!~<>,;:_=?*+#."&§%°()|\[\]$^#\/-]*
([a-zA-Z0-9!~<>,;:_=?*+#."&§%°()|\[\]$^#\/-])\1\1
)
[a-zA-Z0-9!~<>,;:_=?*+#."&§%°()|\[\]$^#\/-]{8,} Match any of the listed 8 or more times
$ End of string
Regex demo

Regexp with a maximum of 2 consecutive equal chars and other options

I'm totally new with regualr expressions and I have to build one with the following requisites:
between 8 and 15 chars
at least 1 alphabetic char (a-z,A-Z)
at least 1 non alphabetic (all the others)
at least 1 CAPITAL letter
at least 1 non-capital letter
maximum of 2 consecutive equal chars (e.g.: 'g' accepted, 'gg' accepted, 'ggg' not)
I tried with this one, but it works only with a maximum of 5 consecutive equal chars (dont understand why). What I'm doing wrong?
var regexp = /^((?=.*[a-z])(?=.*[A-Z])(?=.*[^a-zA-Z])(.{8,15})(?!.*(.)\1{2}))$/;
EDIT it works with
asdfghjkl1Q
asdfghjkl1QQQ
asdfghjkl1QQQQQ
it not works with
asdfghjkl1QQQQQQ
asdfghjkl1QQQQQq
what i'm trying to obtain is:
WORKING with :
asdfghjkl1Q
asdfghjkl1QQ
asdfghjkl11
NOT WORKING with:
asdfghjkl1QQQ
asdfghjkl1QQq
asdfghjkl111
I think you don't need the outer capturing group so you might omit it.
You could first check for the 8,15 characters until the end of the string $ using a lookahead (?=.{8,15}$)
If all the lookaheads match, then match any character one or more times .+
Try it like this:
^(?=.{8,15}$)(?=.*[a-z])(?=.*[A-Z])(?=.*[^a-zA-Z])(?!.*(.)\1{2}).+$

Match exactly 11 occurences of the same digit in a group

I need to match exactly 11 occurences of the same digit in a group, like:
11111111111
55555555555
But not:
11111000111
55552225555
What I've tried so far can get 11 occurences of digits:
/([0-9]){11}/g
/\d{11}/g
But it will match any 11 digits.
I've managed to do this:
/(0{11}|1{11}|2{11}|3{11}|4{11}|5{11}|6{11}|7{11}|8{11}|9{11})/g
Is there any other easier way to do it?
/(\d)\1{10}/
This matches the first digit and uses a reference to that digit \1 to match it ten more times. Note that this will also match if the digit repeats 12 or more times, and if other digits start the string, but this seems to be desired.
You should use backreference: ((\d)\2{10})
The \2 matches "the same thing as was the 2nd caputing group (parentheses)".
https://regex101.com/r/QESWrJ/1

Regular Expression formatting

I have an input box and the condition is to allow the user to enter only numbers, the numbers entered should be in the following format in groups of 4, ex: 4444 5555 and the maximum number of characters to be entered in the textbox should be 9. I am pretty new to regex, so have no clue of how to start. A working sample in fiddle would be of great help.
If the requirement is strictly 10 numbers in the above grouping with spaces in the middle, the regex is simple:
/^\d{4}\s\d{4}\s\d{2}$/
Where \d means that it would only match a numeric character, {4} means that it would look exactly 4 times for the previous match (\d), and in this case that would match 4 numeric characters. \s means one whitespace, and similarly like the {4}, \d{2} matches 2 numeric characters. The ^ and $ mean start of the string to be matched and end of the string to be matched respectively.
Hope this helps.
If the length is fixed then you can just use \d to represent a digit
/^\d\d\d\d \d\d\d\d \d\d\d\d \d\d$/
or use the {n} multiplier instead
/^\d{4} \d{4} \d{4} \d\d$/
if instead the total length is arbitrary and you just want to be sure that every four digits you have a space things are just slightly more complex:
/^(\d{4} )*\d{1,4}$/
the meaning is that you want zero or more groups formed with 4 digits and one space followed by 1 to 4 digits. In the last part you can use {0,4} if you also want to accept an empty string as a valid response.
If you want 1 or more of something use '+'. For example 4+ would be 1 or more consecutive '4's.
Use * to for things that you want 0 or more of!
Use parentheses for groups of characters or groups of other groups.
If you want a space in between, then use the space character between two of them.
It looks like you want 1 or more '4's followed by 0 or more (space followed by 1 or more '4's)
This regular express would match all of the following strings: "4+( 4+)*"
44444
4 44 4
4 4 4
4
4444444444
4 4
44444444444444 44444444444444444 4444444444444444
4444 4444 44
As per example provided this regex will help
/^[0-9][0-9 ]*$/
This represent numbers with spaces in between. For eg. 444 444. But if you put in this way ' 444 444' like first inserting space then start the numbers then it wont allow.
For that you can use /^[0-9 ]*$/
^ represent start and $ represent end. So between start and end you can write numbers with spaces.

Difference between regex repeater and submatch recur

Can anyone explain to me the differences between these two regex approaches:
/(\d)\1/
/(\d){2,}/
As far as I can see they both match for at least one recurrence of a subexpression. If they, in fact, do the same thing, are there any performance issues that distinguish them?
No they don't do the same
/(\d)\1/
matches
11 and 22 and 33
With the brackets you put the matched digit in a capture group and access that variable with \1, so you match two equal digits in a row.
while
/(\d){2,}/
matches
12 and 22 and 123456789 and 22222222
Here you say match two or more ({2,}) digits in a row. This can be different digits.
/(\d)\1/ - Match a digit, capture it in group 1, and then match the same digit again, using a back references.
/(\d){2,}/ - Match 2 digits or more. The last digit will be captured in a group. Each digit is matched independently, they don't have to be the same.

Categories