invalid quantifier javascript error on regex - javascript

What am I doing wrong here?
I'm trying to replace a number in a string with another number using javascript. I have a long string that has the number 1 in it several times. I need to replace the number 1 with 2 in every case except where 1 has another number on either side. I did a bunch of google searches for how to use regex (I'm totally new to regex) and I came up with this.
string.replace(/(?<!\d)1(?!\d)/,2);
Basically, I want the regex to match (and thus replace) every occurrence of the number 1 where it is surrounded by anything except another number. I don't want the match to include the surrounding characters--only the number 1.
I keep getting the invalid quantifier error in my firebug console. What am I doing wrong?

It's this bit: (?<!\d). There's no (?<, only (?:, (?=, and (?!.
JavaScript doesn't have look-behind, but I think you can work around it in this case, like this:
str = str.replace(/(^|\D)1(?!\d)/g, "$12")
That captures the character immediately prior to the digit, then echoes it back ($1 in the replacement string) followed by the new content (2). The ^ near the beginning allows for the digit being the first character in the string.
Live example
Breaking it down:
(^|\D) Match either start-of-string, or a non-digit, and capture the result
1 Match the digit 1...
(?!\d) ...but only if it isn't followed by a digit
And in the replacement, $12 is not "replace with capture group 12" (which is what it looks like to me), but "replace with capture group 1 followed by the digit 2."

Related

Regex finding second string

I'm attempting to get the last word in the following strings.
After about 45 minutes I can't seem to find the right combination of slashes, dashes and brackets.
The closest I've got is
/(?![survey])[a-z]+/gi
It matches the following strings, except for "required" it is returning the match "quired" I'm assuming it's because the re are in the word survey.
survey[1][title]
survey[1][required]
survey[2][anotherString]
You're using a character set, which will exclude any of the characters from being the first character in the match, which isn't what you want. Using plain negative lookahead would be a start:
(?!survey)[a-z]+
But you also want to match the final word, which can be done by matching word characters that are followed with \]$ - that is, by a ] and the end of the string:
[a-z]+(?=\]$)
https://regex101.com/r/rLvsY5/1
If you want to be more efficient, match the whole string, but capture what comes between the square brackets in a capturing group - the last repeated captured group will be in the result:
survey(?:\[(\w+)\])+
https://regex101.com/r/rLvsY5/2
One way to solve this is to match the full line and only capture the part you need.
survey\[\d+\]\[([a-z]+)\]

Javascript regex to make sure that string matches format x:y

I am trying to parse a string which has two numbers, both can be between 1 and 3 digits, and will have a colon in between. Here are some examples:
"1:1"
"1:12"
"12:1"
"123:12"
Also, the given string may also be invalid, and I need to detect if it is. My attempts so far to make sure the string is valid have looked like this: .match(/[1-9]\:[1-9]/);. But then I noticed that this wont work if a string such as this is inputted: "characters12:4characters". How would I go about validating the string to make sure it is in the format x:y?
Any help would be deeply appreciated.
Edit: numbers which contain 0 at the beginning is valid, but may not be given.
You may use
/^\d{1,3}:\d{1,3}$/
See the regex demo
Details
^ - start of a string
\d{1,3} - one, two or three digits (\d is a shorthand character class that matches any digit (it can also be written as a [0-9] character class) and {1,3} is a limited quantifier that matches1 to 3 consecutive occurrences of the quantified subpattern)
: - a colon
\d{1,3} - one, two or three digits
$ - end of the string.

Regex exact match on number, not digit

I have a scenario where I need to find and replace a number in a large string using javascript. Let's say I have the number 2 and I want to replace it with 3 - it sounds pretty straight forward until I get occurrences like 22, 32, etc.
The string may look like this:
"note[2] 2 2_ someothertext_2 note[32] 2finally_2222 but how about mymomsays2."
I want turn turn it into this:
"note[3] 3 3_ someothertext_3 note[32] 3finally_2222 but how about mymomsays3."
Obviously this means .replace('2','3') is out of the picture so I went to regex. I find it easy to get an exact match when I am dealing with string start to end ie: /^2$/g. But that is not what I have. I tried grouping, digit only, wildcards, etc and I can't get this to match correctly.
Any help on how to exactly match a number (where 0 <= number <= 500 is possible, but no constraints needed in regex for range) would be greatly appreciated.
The task is to find (and replace) "single" digit 2, not embedded in
a number composed of multiple digits.
In regex terms, this can be expressed as:
Match digit 2.
Previous char (if any) can not be a digit.
Next char (if any) can not be a digit.
The regex for the first condition is straightforward - just 2.
In other flavours of regex, e.g. PCRE, to forbid the previous
char you could use negative lookbehind, but unfortunately Javascript
regex does not support it.
So, to circumvent this, we must:
Put a capturing group matching either start of text or something
other than a digit: (^|\D).
Then put regex matching just 2: 2.
The last condition, fortunately, can be expressed as negative lookahead,
because even Javascript regex support it: (?!\d).
So the whole regex is:
(^|\D)2(?!\d)
Having found such a match, you have to replace it with the content
of the first capturing group and 3 (the replacement digit).
You can use negative look-ahead:
(\D|^)2(?!\d)
Replace with: ${1}3
If look behind is supported:
(?<!\d)2(?!\d)
Replace with: 3
See regex in use here
(\D|\b)2(?!\d)
(\D|\b) Capture either a non-digit character or a position that matches a word boundary
(?!\d) Negative lookahead ensuring what follows is not a digit
Alternations:
(^|\D)2(?!\d) # Thanks to #Wiktor in the comments below
(?<!\d)2(?!\d) # At the time of writing works in Chrome 62+
const regex = /(\D|\b)2(?!\d)/g
const str = `note[2] 2 2_ someothertext_2 note[32] 2finally_2222 but how about mymomsays2.`
const subst = "$13"
console.log(str.replace(regex, subst))

Specific Length Regular Expression With Padding

Goal: to make a generalized Regular Expression for a fixed length string inside a larger string. This string has a specified padding character, followed by an integer counter that increments. Ideally, there would be some way to say, "I want this group to be of length 10 and contain only one type of character followed by a different character."
I am trying to match this within variable data (could be numbers could be letters could be symbols):
The padding-characters + numbers add up to a specified length, here would be 5.
These are the allowed padding + number combinations.
$$$$1
$$$12
$$123
$1234
Here is an example:
<variable-data> <padding-characters> <numbers> <variable-data>
............... .................... ddddddddd ...............
(where periods are any characters and 'd' is any digit)
Example Data:
ABC $$$$ 1 $!#
Example Regex:
ABC\$*\d+\$!#
Match:
ABC$$$$1$!#
ABC$$$12$!#
ABC$$123$!#
ABC$1234$!#
ABC12345$!#
No Match:
ABC$$123456789$!#
ABC1$2$34$!#
Regex101
What I've Tried:
ABC(?=.{5})\$*\d+\$!#
This does not work because it still matches into the next digits because of \d+. Another thing I tried was
ABC(?=[\$\d]{5}[^\$\d])(\$*\d+)\$!#
Which aims to stop looking after it encounters a non-digit or non $, but that's not helpful since the next part of the string COULD start with a $ or a digit.
The easiest Regex to solve this:
(\$\$\$\$\d|\$\$\$\d\d|\$\$\d\d\d|\$\d\d\d\d|\d\d\d\d\d)
But I am trying to make this more generalized, and there can be a variable amount of padding E.G.
$$$$$$$$$1
$$$$$$$$12
...
You could look ahead to check that you don't have an inverted sequence of padding character and digit within the scope of the next 5 characters, and then require and capture 5 characters that are only digits and padding characters:
ABC(?!.{0,3}\d\$)([\$\d]{5})\$!#
If you need at least one digit, then:
ABC(?!.{0,3}\d\$)([\$\d]{4}\d)\$!#
ABC(?=.{5}\$!#)\$*\d+\$!#
This is very similar to your first attempt, but with the slight difference that the lookahead also contains the terminating string. This gives it something to anchor to, to make sure the regex doesn't match anything more.

Regex to force a specific length and at the same time not starting with a number

I am having trouble building a very complex Regex. These are my constraints:
Length: 8 to 10
Cannot start by a number neither by an underscore
Has at least one capital letter, one number and one character among
the following 3 special characters: _$£
I thought I did it when I got to this:
^([^0-9_])(?=.*[A-Z])(?=.*[0-9])(?=.*[$£_])[A-Za-z0-9$£_]{7,9}$
It correctly fails the 1st statement:
aDf123_ fails because its length is not 8
aDf123_aAAFF fails because its length is more than 10
It correctly fails the 2nd statement:
_aDf1234 fails because it starts with an underscore
1aDf1234 fails because it starts with a number
It correctly fails the 3rd statement:
aaDf1234 fails because it doesn't have any special character
aadf1$34 fails because it doens't have a capital letter
aaDf$£££ fails because it doesn't have a number
And finally, it passes through the validation with a valid string: aaDf$££5
What is the problem? The problem is that the following string fails while it should pass through the validation: Daaa$444
When the capital letter is the first letter my regex doesn't see it. How can I make it see it? I know it is related with the fact that my regex ends with {7,9} instead of {8,10} but I cannot help it because I have to define that it must not start with a number or underscore...
You need to put lookaheads after ^ and replace [^0-9_] with [A-Za-z$£]:
^(?=.*[A-Z])(?=.*[0-9])(?=.*[$£_])[A-Za-z$£][A-Za-z0-9$£_]{7,9}$
See this regex demo.
Else, the first [^0-9_] matches ^, &, etc. that is NOT a digit or _ and the lookaheads only look for the required patterns after the first char. So, any valid string that has a required char only at its beginning will fail.
Alternatively, turn the [^0-9_] into the negative (?![0-9_]) lookahead (and then you will need to replace the {7,9} with {8,10} at the end since the lookahead pattern is non-consuming):
^(?![0-9_])(?=.*[A-Z])(?=.*[0-9])(?=.*[$£_])[A-Za-z0-9$£_]{8,10}$
See this regex demo.

Categories

Resources