I am trying to control a text input field in a react application by only allowing an empty string, digits or an optional plus character at the start.
The regex pattern I am using is the following:
export const phoneNumberTestPattern = new RegExp('^\\+?\\d+?$');
This pattern is used to test the inputs value whenever the input is changed
onChange={ (e) => {
if (e.target.value === '' || phoneNumberTestPattern.test(e.target.value)) {
field.onChange(e.target.value);
}
}}
The pattern is working correctly for allowing only digits. But the optional plus character at the start is not being matched when the onChange event parameter returns a + value as e.target.value.
The event.target.value does return the + as a value when typed in, but the test pattern does not recognize it as something that matches so the field.onChange method is never fired.
I dont understand what the reason for this is, and why the pattern is not matching a plus character at the start of the string being sent to it. Could it be possible the value I am sending to the test pattern is a string and I am trying to match it against a plus operator ?
Any help would be greatly appreciated.
The error is on \d+?. It does not mean an optional sequence of digits. It means a sequence of at least one digit, not greedy.
The * and + quantifiers are, by default, greedy. This means that they attempt to match as much as possible.
For example, the regex a+ matches the entire string aaa. The + qualifier makes the a before it to match all a characters from the input string.
By adding a ? after +, the qualifier becomes lazy and the regex a+? matches only the first a from the input string.
Check it below:
const reGreedy = /a+/;
const reLazy = /a+?/;
console.log(reGreedy.exec('aaa'));
console.log(reLazy.exec('aaa'));
This means that your regex matches the input string only if the input string contains at least one digit at the end.
There are two ways to achieve what you need. One of them is to wrap \d+ in parentheses, like this: (\d+)?. This way \d+ matches a sequence of one or more digits and the ? after it tells that this sequence is optional.
The same thing can be achieved by using * instead of +, and ? is not needed any more in this case. \d* matches a sequence of zero or more digits.
Also, if you create a RegExp using a regex literal there is no need to escape the backslash.
Be aware that this regex also matches the empty string (now both the + and the number are optional). Your check against the empty string can be removed from the code.
All in all, your code should be like:
export const phoneNumberTestPattern = /^\+?\d*$/;
onChange={ (e) => {
if (phoneNumberTestPattern.test(e.target.value)) {
field.onChange(e.target.value);
}
}}
Check the regex online.
Maybe u can try this regex pattern
^(?:+)?\d+$
Like other answers say, you could use /^(?:|\+?\d+)$/
const populated = '+123456'
const unpopulated = ''
const pattern = /^(?:|\+?\d+)$/
console.log(`populated: ${pattern.test(populated)}`)
console.log(`unpopulated: ${pattern.test(unpopulated)}`)
But an alternative is to use the pattern attribute of the <input> tag:
input:valid {
background-color: palegreen;
}
input:invalid {
background-color: lightpink;
}
<input id="id-inp" type="tel" pattern="^\+?\d+?$">
Related
Given a regular expression, I can easily decide where to start looking for a match from in a string using lastIndex.
Now, I want to make sure that the match I get doesn't go past a certain point in the string.
I would happily enclose the regular expression in a non-capturing group and append, for instance, (?<=^.{0,8}).
But how can I achieve the same goal without lookbehinds, that still aren't globally supported?
Note:
While it might be the only reasonable fallback, slicing the string is not a good option as it results in a loss of context for the search.
Example
https://regex101.com/r/7bWtSW/1
with the base regular expression that:
matches the letter 'a', at least once and as many times as possible
as long as an 'X' comes later
We can see that we can achieve our goal with a lookbehind: we still get a match, shorter.
However, if we sliced the string, we would lose the match (because the lookahead in the base regular expression would fail).
Your pattern in the regex demo (?:a+(?=.*X))(?<=^.{0,4}) uses a lookbehind assertion with that can yield multiple separate matches.
See a regex demo for the same pattern with multiple matches in the same string
Without using a lookbehind, you can not get those separate matches.
What you might do is use an extra step to get all the matches for consecutive a char over matched part that fulfills the length restriction (In this case the group 1 value)
^([^\nX]{0,3}a)[^\nX]*X
The pattern matches
^ Start of string
( Capture group 1
[^\nX]{0,3}a Match 0-3 times a char other than a newline or X and then match a
) Close group 1
[^\nX]*X Match optional chars other than a newline or X and then match X
Regex demo
const regex = /^([^\nX]{0,3}a)[^\nX]*X/;
[
"aaaaaaaaX",
"baaaaaaaaX",
"bbaaaaaaaaX",
"bbbaaaaaaaaX",
"bbbbaaaaaaaaX",
"babaaaaaaaaX",
"aX",
"abaaX"
].forEach(s => {
const m = s.match(regex);
if (m) {
console.log(m[1].match(/a+/g))
}
})
Slice the match instead of slicing the string.
In your example, you want the match to account for the positive lookahead for X. But X is outside the limited scope, so we don't want to limit the search scope, essentially slicing the string, instead we want to limit match length relative to its position in the string.
To do that we'll use the index property of the returned match array.
const string = 'aaaaaaaX'
const regex = /a+(?=X)/
function limitedMatch(string, regex, lastIndex) {
const match = string.match(regex)
const {index} = match;
const matchLength = Math.max(lastIndex - index,0)
return match[0].slice(0, matchLength)
}
console.log(limitedMatch(string, regex, 4))
console.log(limitedMatch(string, regex, 2))
I have the regular expression:
const regex = /^\d*\.?\d{0,2}$/
and its inverse (I believe) of
const inverse = /^(?!\d*\.?\d{0,2}$)/
The first regex is validating the string fits any positive number, allowing a decimal and two decimal digits (e.g. 150, 14., 7.4, 12.68). The second regex is the inverse of the first, and doing some testing I'm fairly confident it's giving the expected result, as it only validates when the string is anything but a number that may have a decimal and two digits after (e.g. 12..05, a5, 54.357).
My goal is to remove any characters from the string that do not fit the first regex. I thought I could do that this way:
let myString = '123M.45';
let fixed = myString.replace(inverse, '');
But this does not work as intended. To debug, I tried having the replace character changed to something I would be able to see:
let fixed = myString.replace(inverse, 'ZZZ');
When I do this, fixed becomes: ZZZ123M.45
Any help would be greatly appreciated.
I think I understand your logic here trying to find a regex that is the inverse of the regex that matches your valid string, in the hopes that it will allow you to remove any characters that make your string invalid and leave only the valid string. However, I don't think replace() will allow you to solve your problem in this way. From the MDN docs:
The replace() method returns a new string with some or all matches of a pattern replaced by a replacement.
In your inverse pattern you are using a negative lookahead. If we take a simple example of X(?!Y) we can think of this as "match X if not followed by Y". In your pattern your "X" is ^ and your "Y" is \d*\.?\d{0,2}$. From my understanding, the reason you are getting ZZZ123M.45 is that it is finding the first ^ (i.e, the start of the string) that is not followed by your pattern \d*\.?\d{0,2}$, and since 123M.45 doesn't match your "Y" pattern, your negative lookahead is satisfied and the beginning of your string is matched and "replaced" with ZZZ.
That (I think) is an explanation of what you are seeing.
I would propose an alternative solution to your problem that better fits with how I understand the .replace() method. Instead of your inverse pattern, try this one:
const invalidChars = /[^\d\.]|\.(?=\.)|(?<=\.\d\d)\d*/g
const myString = '123M..456444';
const fixed = myString.replace(invalidChars, '');
Here I am using a pattern that I think will match the individual characters that you want to remove. Let's break down what this one is doing:
[^\d\.]: match characters that are not digits
\.(?=\.): match . character if it is followed by another . character.
(?<=\.\d\d)\d*: match digits that are preceded by a decimal and 2 digits
Then I join all these with ORs (|) so it will match any one of the above patterns, and I use the g flag so that it will replace all the matches, not just the first one.
I am not sure if this will cover all your use cases, but I thought I would give it a shot. Here's a link to a breakdown that might be more helpful than mine, and you can use this tool to tweak the pattern if necessary.
I don't think you can do this
remove any characters from the string that do not fit the first regex
Because regex matching is meant for the entire string, and replace is used to replace just a PART inside that string. So the Regex inside replace must be a Regex to match unwanted characters only, not inverted Regex.
What you could do is to validate the string with your original regex, then if it's not valid, replace and validate again.
//if (notValid), replace unwanted character
// replace everything that's not a dot or digit
const replaceRegex = /[^\d.]/g; // notice g flag here to match every occurrence
const myString = '123M.45';
const fixed = myString.replace(replaceRegex, '');
console.log(fixed)
// validate again
Sorry for very useless question!
I need regular expression for check this type of string
+7
i was try .replace(/^+[0-9][^\d]/g, '') but it give me all another type of math symbols, i need
First symbol +
Second one number 1 - 9
your regex needs to be
^\+[0-9][^\d]
if you want to match all numbers starting with + you can use
/\+\d+/g
Note this would match +73ab and return +73
If you want just numbers you can use
/\b\+\d+\b/g
Plus + is a special character used in regular expressions to indicate one or more occurrences of the expression before it. That's why it does not work in your example. You should escape it with \.
If you want to get all numbers prefixed by plus in multiline text, you can use:
/\+\d+/gm
For Example:
var numbers = 'skdlfjlk +7fsd \r\nsd;flk+123'.match(/\+\d+/gm);
console.log(numbers); // => ["+7", "+123"]
If by "number" you actually meaning digit from 1 to 9, and you are interested only in first occurrence in the string, you can use:
/\+[1-9]/m
If, in addition, you need it to be the beginning of the string, you can use just:
/^\+[1-9]/
I have an input field that should only accept characters used in a currency syntax (dollar sign, numbers, commas, and decimals). How can I write my REGEX to check if a string contains atleast one character that is NOT from the above listed characters?
I've tried the following, but the problem with this expression is that if one valid character is present in the string it throws the 'else' statement. (unitPriceVal is the user input string)
I want to write a regex that checks if the WHOLE string consists of the valid Currency, if true run the else statement
validCurrency = /([0-9\$.,])/;
if (!unitPriceVal.match(validCurrency) || unitPriceVal == "") {
unitPrice.setValueState("Error");
} else {
unitPrice.setValueState("None");
}
},
I want to write a regex that checks if the WHOLE string consists of the valid Currency
To check the whole string, anchor the match to the beginning and end of the input, using ^ and $, and make sure what's in between is a sequence (+) of allowable characters:
/^[\d$.,]+$/;
You don't need parentheses. You also don't need to escape the $ inside the character set. Finally, you can use \d for a digit.
Often, it's better to use the input element's pattern attribute to do this check. In that case, you don't need the anchors (they're implied):
<input pattern="[\d$.,]+">
How can I write my REGEX to check if a string contains at least one
character that is NOT from the above listed characters?
function validUnitPrice(unitPriceVal) {
let invalidCurrency = /[^0-9\$.,]/;
return unitPriceVal.search(invalidCurrency) == -1;
}
The ^ character as the first character inside a character set ([^...]) negates the character set i.e. matching characters not in the set.
I have one text input.
I wrote a regex for masking all special characters except . and -. Now if by mistake the user enters two . (dots) in input, then with the current regex
var valueTest='225..36'
valueTest.match(/[^-.\d]/)
I expected that the number will not pass this condition
How to handle this case. I just want one . (dot) in input field since it is a number.
I think you mean this,
^-?\d+(?:\.\d+)?$
DEMO
It allows positive and negative numbers with or without decimal points.
EXplanation:
^ Asserts that we are at the start.
-? Optional - symbol.
\d+ Matches one or more numbers.
(?: start of non-capturing group.
\. Matches a literal dot.
\d+ Matches one or more numbers.
? Makes the whole non-capturing group as optional.
$ Asserts that we are at the end.
if you just want to handle number ,you can try this:
valueTest.match(/^-?\d+(\.\d+)?$/)
You can probably avoid regex altogether with this case.
For instance
String[] input = { "225.36", "225..36","-225.36", "-225..36" };
for (String s : input) {
try {
Double d = Double.parseDouble(s);
System.out.printf("\"%s\" is a number.%n", s);
}
catch (NumberFormatException nfe) {
System.out.printf("\"%s\" is not a valid number.%n", s);
}
}
Output
"225.36" is a number.
"225..36" is not a valid number.
"-225.36" is a number.
"-225..36" is not a valid number.
Use below reg ex it will meet your requirements.
/^\d+(.\d+)?$/