regex: remove leading zeros, but keep single zero - javascript

I have an input field to which I have tied a formatting function that is triggered whenever the field loses focus.
What I aim to achieve is that I remove all the leading zeros from an input and I did achieve that with the below line. However, when the user wants to enter a single 0 or something like 0000 I still want that field to end with the value 0 (single). With .replace(/^0+/, '') it would remove every zero and return just an empty string. Someone knows what regex could handle this?
const formatNumber = ($field) => {
var number = $field.val().replace(/\./g, '').replace(/\s/g, '').replace(/^0+/, '');
return number;
};
note: if(number === "") number = "0" is not an option.
edit1:: I noticed there seems to be a bit of confusion. e.g "0009825" need to become 9825 and not 09825. the only instance where i want a 0 up front is when the value is simply zero.

You ay use this regex replacement:
.replace(/^(?:0+(?=[1-9])|0+(?=0$))/mg, '')
RegEx Demo
RegEx Details:
^: Start
(?:: Start capture group
0+(?=[1-9]): Match 1 or more zeroes that must be followed by 1-9
|: OR
0+(?=0$): Match 1 or more zeroes that must be followed by one 0 and end
): End capture group
Replacement is empty string which will leave a single 0 if there are only zeroes in string otherwise will remove leading zeroes.
Alternative solution using a capture group:
str = str.replace(/^0+(0$|[1-9])/mg, '$1');

A simple reg exp with leading zeros and match one digit in a capture group
const cleanZeros = str => str.replace(/^0+(\d)/, '$1')
var tests = ["0009876","0", "0000", "9999", "0090000"]
tests.forEach( s => console.log(s, cleanZeros(s)))

Related

jQuery: Unable to use RegExp to search for exactly "+3.00" or "-3.00"

I'm struggling with finding the correct RegExp to match number with plus (+) or minus (-) sign at the end.
I have a select list of number ranging from 0.00- to 40.00- and 0.00+ to 40.00-. I'm using the following RegExp to filter out non matching records:
$("#MySelectBox").change(function() {
var filter = $(this).val()
// If the list item does not contain the numbers phrase fade it out
if ($(this).text().search(new RegExp('\\b'+filter+'\\b', "i")) < 0) {
$(this).hide();
} else {
$(this).show();
}
However, it will show both + and - numbers. For example: if filter = 3.00+ then it will return both 3.00+ and 3.00- values.
Any ideas how to get the exact match?
[\+-]\d{1,2}\.00
Will match + or -, followed by one or two digits (\d{1,2}), followed by .00.
However, RegExes don't have "greater than 40" kind of logic. They only match patterns.
There are useful tools to help you, like Rexegpal
So with your brief:
Check string matches pattern: "+xx.xx" or "-xx.xx"
Only numbers between -40 or +40
Omit results out of bounds
This could be a good way to achieve your desired result.
Notes: (1) Unsure if you wanted to enforce the demical point, (2) there are certainly multiple ways to achieve your result, this is is just one.
const regex = /^[\-\+]\d+\.*\d*$/;
const tests = ["41", "20", "+20", "-20", "+20.00", "-20.20", "20.20"];
const passedTests = tests.filter(number => {
const parsedNumber = Number.parseFloat(number);
const isValid = !!number.match(regex) && parsedNumber > -40 && parsedNumber < 40;
console.log(`Test ${number}, result: ${isValid}`);
return isValid;
});
console.log(passedTests);
To get an exact match for a number with plus (+) or minus (-) sign at the end and from 0.00- to 40.00- and 0.00+ to 40.00+, you can use:
^(?:(?:[0-9]|[123]\d)\.\d\d|40\.00)[+-]$
^ Start of string
(?: Non capture group for the alternation |
(?:[0-9]|[123]\d) Match either a digit 0-9 or a number 10 - 39
\.\d\d Match a . and 2 digits 0-9
| Or
40\.00 Match 40.00
) Close group
[+-] Match either + or -
$ End of string
Regex demo
In Javascript you can use
const regex = /^(?:(?:[0-9]|[123]\d)\.\d\d|40\.00)[+-]$/;
If the value is not the only value in the string, you could start with pattern with a word boundary \b and assert a whitespace boundary at the right (?!\S)
\b(?:(?:[0-9]|[123]\d)\.\d\d|40\.00)[+-](?!\S)
Regex demo

Is it possible to have one regex that solves this task?

string = '1,23'
When a comma is present in the string, I want the regex to match the first digit (\n) after the comma e.g.2.
Sometimes the comma will not be there. When it's not present, I want the regex to match the first digit of the string e.g. 1.
Also, we can't reverse the order of the string to solve this task.
I am genuinely stuck. The only idea I had was prepending this: [,|nothing]. I tried '' to mean nothing but that didn't work.
You can match an optional sequence of chars other than a comma and then a comma at the start of a string, and then match and capture the digit with
/^(?:[^,]*,)?(\d)/
See the regex demo.
Details
^ - start of string
(?:[^,]*,)? - an optional sequence of
[^,]* - 0 any chars other than a comma
, - a comma
(\d) - Capturing group 1: any digit
See the JavaScript demo:
const strs = ['123', '1,23'];
const rx = /^(?:[^,]*,)?(\d)/;
for (const s of strs) {
const result = (s.match(rx) || ['',''])[1];
// Or, const result = s.match(rx)?.[1] || "";
console.log(s, '=>', result);
}

Regex to extract two numbers with spaces from string

I have problem with simple rexex. I have example strings like:
Something1\sth2\n649 sth\n670 sth x
Sth1\n\something2\n42 036 sth\n42 896 sth y
I want to extract these numbers from strings. So From first example I need two groups: 649 and 670. From second example: 42 036 and 42 896. Then I will remove space.
Currently I have something like this:
\d+ ?\d+
But it is not a good solution.
You can use
\n\d+(?: \d+)?
\n - Match new line
\d+ - Match digit from 0 to 9 one or more time
(?: \d+)? - Match space followed by digit one or more time. ( ? makes it optional )
let strs = ["Something1\sth2\n649 sth\n670 sth x","Sth1\n\something2\n42 036 sth\n42 896 sth y"]
let extractNumbers = str => {
return str.match(/\n\d+(?: \d+)?/g).map(m => m.replace(/\s+/g,''))
}
strs.forEach(str=> console.log(extractNumbers(str)))
If you need to remove the spaces. Then the easiest way for you to do this would be to remove the spaces and then scrape the numbers using 2 different regex.
str.replace(/\s+/, '').match(/\\n(\d+)/g)
First you remove spaces using the \s token with a + quantifier using replace.
Then you capture the numbers using \\n(\d+).
The first part of the regex helps us make sure we are not capturing numbers that are not following a new line, using \ to escape the \ from \n.
The second part (\d+) is the actual match group.
var str1 = "Something1\sth2\n649 sth\n670 sth x";
var str2 = "Sth1\n\something2\n42 036 sth\n42 896 sth y";
var reg = /(?<=\n)(\d+)(?: (\d+))?/g;
var d;
while(d = reg.exec(str1)){
console.log(d[2] ? d[1]+d[2] : d[1]);
}
console.log("****************************");
while(d = reg.exec(str2)){
console.log(d[2] ? d[1]+d[2] : d[1]);
}

Regex - Numeric regex with . and ,

I have to create a regex that allows the user to input only a number (using . or ,)
so these examples are both valid:
8,5
8.5
here's my current code
private regex: RegExp = new RegExp(/^\d*[\,\.]{0,1}\d{1,2}/g);
However this allows me to input 8.,5 which is obviously bad. How can I change my regex so that the user can only place 1 of the decimal characters , OR .?
EDIT:
I've tried alot of answers, but most of them don't work (I can't place any decimal characters). Basically I'm creating a directive in angular that converts <input type="text"> to an numeric input (I can't use type="number")
Here's my directive code (see Angular2 - Input Field To Accept Only Numbers)
#Directive({
selector: "[OnlyNumber]"
})
export class OnlyNumberDirective {
// Allow decimal numbers. The \. is only allowed once to occur
private regex: RegExp = new RegExp(/^(?=.+)\d*(?:[\,\.]\d{1,2})?$/g);
// Allow key codes for special events. Reflect :
// Backspace, tab, end, home
private specialKeys: Array<string> = ["Backspace", "Tab", "End", "Home"];
constructor(private el: ElementRef) {
}
#HostListener("keydown", ["$event"])
onKeyDown(event: KeyboardEvent) {
// Allow Backspace, tab, end, and home keys
if (this.specialKeys.indexOf(event.key) !== -1) {
return;
}
let current: string = this.el.nativeElement.value;
let next: string = current.concat(event.key);
if (next && !String(next).match(this.regex)) {
event.preventDefault();
}
}
}
and here's how I use it in my template:
<mat-form-field class="numeric-textbox">
<input matInput
OnlyNumber
#model="ngModel"
placeholder="{{ label }}"
[ngModel]="selectedValue"/>
<mat-error><ng-content></ng-content></mat-error>
</mat-form-field>
You should specify the end of input string with $ without which a partial match will happen. You shouldn't look for \d* unless you want to match values like .5 or ,5 otherwise they will match as a valid input.
^\d+(?:[.,]\d{1,2})?$
Note: You don't need to escape dots or commas inside a character class and a quantifier like [.,]{0,1} is literally equal to [.,]?
Live demo:
document.getElementById("number").addEventListener("keyup",function(e) {
console.log(this.value.match(/^\d+(?:[.,]\d{1,2})?$/));
});
<input type="text" id="number" placeholder="Enter a number">
Update, based on comments
^(?![.,]?$)\d*[,.]?(?:\d{1,2})?$
This allows any number optionally followed or preceded by a decimal point or comma.
Live demo
The regex is correct, buy you just need to match the whole string:
^ start of the string
$ end of the string
However, the regex can be improved with:
^ : for start of string
\d+ : for at least 1 digit
(
[\,\.] : 1 comma
\d{1,2} : followed by 1 digit or two
)? : keep this optionnal. We can get numbers without commas
$ : end of string
Final regex may be:
/^\d+([\,\.]\d{1,2})?$/
Try: /^(?=.+)\d*(?:[,.]\d{1,2})?$/g
let regex = /^(?=.+)\d*(?:[,.]\d{1,2})?$/g,
strings = ["5", "50", "500", ".5", ",5","5.5","5,5", "5.55", "5,55", "5.555", "5,555", "5,,5", "5..5", "5,.5", "5.,5", "5,", "5."];
strings.forEach((string) => {
console.log(`${regex} ${string.match(regex) ? `matches ${string.match(regex)}`: `has no match for ${string}`}`);
});
This will match:
From the start, lookahead to make sure that there are characters present (one or more), and then begin matching: any amount of digits (0 or more), and the following optional: a comma or a dot, and then 1 or 2 digits before the end of the string.
Your regex is perfectly fine, you just need to specify the line's termination. You're currently matching 8 from 8,.5 which is likely why you're experiencing issues with your regex. I assume you're using JavaScript's test() function and getting true as a response for that string. Simply append $ to your regex and you'll get the correct answer. You can also simplify your regex to the following (also commented out in the snippet below). You can also probably drop the g flag as you're trying to match the string once, not multiple times:
^\d*[,.]?\d{1,2}$
What you're matching:
var a = ['8.5', '8,5', '.5', ',5', '8.,5']
var r = /^\d*[\,\.]{0,1}\d{1,2}/g
a.forEach(function(s){
console.log(s.match(r))
})
What you should be matching:
var a = ['8.5', '8,5', '.5', ',5', '8.,5']
var r = /^\d*[\,\.]{0,1}\d{1,2}$/g
// var r = /^\d*[,.]?\d{1,2}$/
a.forEach(function(s){
console.log(s.match(r))
})

Javascript Remove all charater except leading - , one dot and digits

First of all this question is not same as
strip non-numeric characters from string or
Regex to replace everything except numbers and a decimal point
I want to convert a string with valid number like.
--1234// will be -1234
-123-123 will be -123123
12.123.3 will be 12.1233
-123.13.123 will be -123.13123
I tried those
number.replace(/[^0-9.-]/g, '') //it accepts multiple . and -
number.replace(/[^0-9.]-/g, '').replace(/(\..*)\./g, '$1');//it accepts multiple minus
I am facing Problem with leading minus sign.
How I can convert a string which will remove all characters except leading -(remove other minus),digits and only one dot(remove other dots)
Here I am sharing my solution.
Lets assume the string is a;
//this will convert a to positive integer number
b=a.replace(/[^0-9]/g, '');
//this will convert a to integer number(positive and negative)
b=a.replace(/[^0-9-]/g, '').replace(/(?!^)-/g, '');
//this will convert a to positive float number
b=a.replace(/[^0-9.]/g, '').replace(/(..*)./g, '$1');
//this will convert a to float number (positive and negative)
b=a.replace(/[^0-9.-]/g, '').replace(/(..*)./g, '$1').replace(/(?!^)-/g, '');
Update for floating number.(solves copy paste problem)
//For positive float number
b=a.replace(/[^0-9.]/g, '').replace('.', 'x').replace(/\./g,'').replace('x','.');
//For Negative float number
b=a.replace(/[^0-9.-]/g, '').replace('.', 'x').replace(/\./g,'').replace('x','.').replace(/(?!^)-/g, '');
Based on #Shaiful Islam's answer, I added one more code.
var value = number
.replace(/[^0-9.-]/g, '') // remove chars except number, hyphen, point.
.replace(/(\..*)\./g, '$1') // remove multiple points.
.replace(/(?!^)-/g, '') // remove middle hyphen.
.replace(/^0+(\d)/gm, '$1'); // remove multiple leading zeros. <-- I added this.
Result
00.434 => 0.434
Not very clean, but works!
var strings = ["-1234","-123-123","12.123.3", "-123.13.123"];
strings.forEach(function(s) {
var i = 0;
s = s.replace(/(?!^)-/g, '').replace(/\./g, function(match) {
return match === "." ? (i++ === 0 ? '.' : '') : '';
});
console.log(s);
});
In your sample data given below,
--1234
-123-123
12.123.3
-123.13.123
-(minus sign or hyphen) causes no problem because it's place is only before digits and not between digits. So this can be solved using following regex.
Regex: -(?=-)|(?<=\d)-(?=\d+(-\d+)?$) and replace with empty string.
Regex101 Demo
However, the position of .(decimal) cannot be determined. Because 123.13.123 could also mean 123.13123 and 12313.123.
Without regex, you can map over the characters this way:
// this function takes in one string and return one integer
f=s=>(
o='', // stands for (o)utput
d=m=p=0, // flags for: (d)igit, (m)inus, (p)oint
[...s].map(x=> // for each (x)char in (s)tring
x>='0'&x<='9'? // if is number
o+=x // add to `o`
:x=='-'? // else if is minus
m||(p=0,m=o=x) // only if is the first, reset: o='-';
:x=='.'? // else if is point
p||(p=o+=x) // add only if is the first point after the first minus
:0), // else do nothing
+o // return parseInt(output);
);
['--1234','-123-123','12.123.3','-123.13.123'].forEach(
x=>document.body.innerHTML+='<pre>f(\''+x+'\') -> '+f(x)+'</pre>')
Hope it helps.
My solution:
number.replace(/[^\d|.-]/g, '') //removes all character except of digits, dot and hypen
.replace(/(?!^)-/g, '') //removes every hypen except of first position
.replace(/(\.){2,}/g, '$1') //removes every multiplied dot
It should then formatted to the proper locale setting using Intl.NumberFormat.

Categories