Remove first zero values from string using regex - regex

I've created a string value using padStart method (padLeft), for example:
"5".padStart(19, "0")
which results into "0000000000000000005"
How can I get that 5 back using regex?
I've tested this:
/^0*(\d+)$/.exec(d)[1]
which return 5 correctly.
But this regex returns null for something like "00000012.22"
Samples:
5 > 5
005 > 5
0011.22 > 11.22 >> This is a first problem!
00100 >> 100
001001 >> 1001
00.5 >> 0.5 This is a second problem!
Working codes but without regex:
function toDb(d) {
if (d == null) return null;
var precisionIndex = d.indexOf('.');
return d.toString().padStart((29 + precisionIndex + 1), '0');
}
function fromDb(d) {
if (d == null) return null;
d = d.replace(/^0+/, ''); // I'd like to use regex here
if (d.indexOf('.') == 0) // I'd like to use regex here
d = '0' + d; // I'd like to use regex here
return d;
}
fromDb(toDb('0.5')) returns 0.5 for me. But I'd like to use regex in my codes.

Use String#replace method to replace leading 0.
console.log(
"0000000000000000005".replace(/^0+(?=\d)/, '')
)
console.log(
"000000000000000000.5".replace(/^0+(?=\d)/, '')
)
In the regex start anchor(^) assert the beginning position of the string and 0+ matches combination one or more repetition of 0, altogether ^0+ matches 0s at the beginning.
UPDATE : To avoid removing 0 just before the . use positive look ahead assertion, (?=\d) match up to the 0 which follows a digit.

Related

The first digit matches the last digit in a four-digits number

I'm trying to find numbers that start and end with the same digit and have similar numbers in between the two digits. Here are some examples:
7007 1551 3993 5115 9889
I tried the following regular expression to identify the first and the last digit. However, no number was selected.
^(\d{1})\1$
I appreciate your help.
Use this:
(\d)(\d)\2+\1
Capture the first and second digits separately, then match them in the reverse order.
Demo
Maybe,
^(\d)(\d)\2+\1$
might be an option to look into.
RegEx Demo
If you wish to simplify/update/explore the expression, it's been explained on the top right panel of regex101.com. You can watch the matching steps or modify them in this debugger link, if you'd be interested. The debugger demonstrates that how a RegEx engine might step by step consume some sample input strings and would perform the matching process.
Your regex will match two digit numbers where both digits are the same. You just need to expand it: (\d)(\d)\2\1
As well, since the numbers are on the same line, use word boundaries (\b) instead of line boundaries (^ and $).
\b(\d)(\d)\2\1\b
BTW {1} is redundant
Demo on regex101
Simple JS way.
let a = "7007 1551 3393 5115 9883";
a = a.split(" ");
let ans = [];
a.forEach((val) => {
let temp = val.split("");
if (temp && temp[0] === temp[temp.length - 1]) {
temp = temp.slice(1,temp.length-1);
ans.push(temp.slice(0,temp.length).every( (val, i, arr) => val === arr[0] )) ;
} else {
ans.push(false);
}
});
console.log(ans);
Regular Expression:
let a = "7007 1551 3393 5115 9883";
a = a.split(" ");
let ans = [];
a.forEach((val) => {
let reg = /(\d)(\d*)(\d)/gi;
let match = reg.exec(val);
if (match && match.length > 3 && match[1] === match[3]) {
let temp = match[2];
temp = temp.split("");
temp = temp.slice(0,temp.length);
ans.push(temp.every( (val, i, arr) => val === arr[0] )) ;
} else {
ans.push(false);
}
});
console.log(ans);

Regex: Any letters, digit, and 0 up to 3 special chars

It seems I'm stuck with a simple regex for a password check.
What I'd like:
8 up to 30 symbols (Total)
With any of these: [A-Za-z\d]
And 0 up to 3 of these: [ -/:-#[-`{-~À-ÿ] (Special list)
I took a look here and then I wrote something like:
(?=.{8,15}$)(?=.*[A-Za-z\d])(?!([ -\/:-#[-`{-~À-ÿ])\1{4}).*
But it doesn't work, one can put more than 3 of the special chars list.
Any tips?
After shuffling your regex around a bit, it works for the examples you provided (I think you made a mistake with the example "A#~` C:", it should not match as it has 6 special chars):
(?!.*(?:[ -\/:-#[-`{-~À-ÿ].*){4})^[A-Za-z\d -\/:-#[-`{-~À-ÿ]{8,30}$
It only needs one lookahead instead of two, because the length and character set check can be done without lookahead: ^[A-Za-z\d -/:-#[-`{-~À-ÿ]{8,30}$
I changed the negative lookahead a bit to be correct. Your mistake was to only check for consecutive special chars, and you inserted the wildcards .* in a way that made the lookahead never hit (because the wildcard allowed everything).
Will this work?
string characters = " -/:-#[-`{-~À-ÿ";
string letters = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz";
string[] inputs = {
"AABBCCDD",
"aaaaaaaa",
"11111111",
"a1a1a1a1",
"AA####AA",
"A1C EKFE",
"AADE F"
};
foreach (string input in inputs)
{
var counts = input.Cast<char>().Select(x => new { ch = characters.Contains(x.ToString()) ? 1 : 0, letter = letters.Contains(x.ToString()) ? 1 : 0, notmatch = (characters + letters).Contains(x) ? 0 : 1}).ToArray();
Boolean isMatch = (input.Length >= 8) && (input.Length <= 30) && (counts.Sum(x => x.notmatch) == 0) && (counts.Sum(x => x.ch) <= 3);
Console.WriteLine("Input : '{0}', Matches : '{1}'", input, isMatch ? "Match" : "No Match");
}
Console.ReadLine();
I would use: (if you want to stick to Regex)
var specialChars = #" -\/:-#[-`{-~À-ÿ";
var regularChars = #"A-Za-z\d";
if (Regex.Match(password,$"^(.[{regularChars}{specialChars}]{7,29})$").Success && Regex.Matches(password, $"[{specialChars}]").Count<=3))
{
//Password OK
}
If consists of:
Check Length and if password contains illegal characters
Check if ony contains 3 times special char
A litle faster:
var specialChars = #" -\/:-#[-`{-~À-ÿ";
var regularChars = #"A-Za-z\d";
var minChars = 8;
var maxChars = 30;
if (password.Length >= minChars && password.Length <= maxChars && Regex.Match(password,$"^[{regularChars}{specialChars}]+$").Success && Regex.Matches(password, $"[{specialChars}]").Count<=3))
{
//Password OK
}
Newbie here..I think I've managed to get what you need but one of the test cases you shared was kinda weird..
A#~` C:
OK -- Match (3 specials, it's okay)
Shouldn't this be failed because it has more than 3 specials?
Could you perhaps try this? If it works I'll type out the explanations for the regex.
https://regex101.com/r/KCL6R1/2
(?=^[A-Za-z\d -\/:-#[-`{-~À-ÿ]{8,30}$)^(?:[A-Za-z\d]*[ -\/:-#[-`{-~À-ÿ]){0,3}[A-Za-z\d]*$

Regex exclude exact digit from digits

Hello my fellow dream builders.
I am parsing time from twitter and I am using this regex:
{
match = /^[1]/.exec(obj.tweetTime);
if(match != null){
time = "1 hour ago";
}
else
{
match = /^[0-9]{1,2}/.exec(obj.tweetTime);
time = match + " hours ago";
}
}
My question is, if there is simpler way to do this? As you can see, I have 2 digits for time. I just want to format my print right. Hour/Hours as you can see.
Is it possible to write only 1 regex and use only 1 conditional bracket?
PS: I am beginner at regex, and I know /^[0-9]{1,2}/ allow numbers from 0 to 99 practically, but as I said it works for my needs, just asking if it is possible to do this properly, since I lack knowledge.
Thank you, much love <3
I would do it like this:
var match = obj.tweetTime.match(/^\d+$/);
if (match) {
var time = match[0] + ' hour' + (match[0] == 1 ? '' : 's') + ' ago';
}
EDIT Turns out the string is formatted! In which case:
var match = obj.tweetTime.match(/^(\d+)([smhd])$/);
if (match) {
var units = { s: 'second', m: 'minute', h: 'hour', d: 'day' },
time = match[1] + ' ' + units[match[2]] + (match[1] == 1 ? '' : 's') + ' ago';
}
To explain the regex:
^ Anchor matches to the beginning of the string
(\d+) Capture one or more digits in first group
([smhd]) Capture s, m, h or d in second group
$ Anchor to end of string

Validate mathematical expressions using regular expression?

I want to validate mathematical expressions using regular expression. The mathematical expression can be this
It can be blank means nothing is entered
If specified it will always start with an operator + or - or * or / and will always be followed by a number that can have
any number of digits and the number can be decimal(contains . in between the numbers) or integer(no '.' symbol within the number).
examples : *0.9 , +22.36 , - 90 , / 0.36365
It can be then followed by what is mentioned in point 2 (above line).
examples : *0.9+5 , +22.36*4/56.33 , -90+87.25/22 , /0.36365/4+2.33
Please help me out.
Something like this should work:
^([-+/*]\d+(\.\d+)?)*
Regexr Demo
^ - beginning of the string
[-+/*] - one of these operators
\d+ - one or more numbers
(\.\d+)? - an optional dot followed by one or more numbers
()* - the whole expression repeated zero or more times
You could try generating such a regex using moo and such:
(?:(?:((?:(?:[ \t]+))))|(?:((?:(?:\/\/.*?$))))|(?:((?:(?:(?<![\d.])[0-9]+(?![\d.])))))|(?:((?:(?:[0-9]+\.(?:[0-9]+\b)?|\.[0-9]+))))|(?:((?:(?:(?:\+)))))|(?:((?:(?:(?:\-)))))|(?:((?:(?:(?:\*)))))|(?:((?:(?:(?:\/)))))|(?:((?:(?:(?:%)))))|(?:((?:(?:(?:\()))))|(?:((?:(?:(?:\)))))))
This regex matches any amount of int, float, braces, whitespace, and the operators +-*/%.
However, expressions such as 2+ would still be validated by the regex, so you might want to use a parser instead.
If you want negative or positive expression you can write it like this>
^\-?[0-9](([-+/*][0-9]+)?([.,][0-9]+)?)*?$
And a second one
^[(]?[-]?([0-9]+)[)]??([(]?([-+/*]([0-9]))?([.,][0-9]+)?[)]?)*$
With parenthesis in expression but doesn't count the number you will need method that validate it or regex.
// the method
public static bool IsPairParenthesis(string matrixExpression)
{
int numberOfParenthesis = 0;
foreach (char character in matrixExpression)
{
if (character == '(')
{
numberOfParenthesis++;
}
if (character == ')')
{
numberOfParenthesis--;
}
}
if (numberOfParenthesis == 0)
{ return true; }
return false;
}
This is java regex, but this is only if not have any braces
[+\-]?(([0-9]+\.[0-9]+)|([0-9]+\.?)|(\.?[0-9]+))([+\-/*](([0-9]+\.[0-9]+)|([0-9]+\.?)|(\.?[0-9]+)))*
Also this with braces in java code
In this case I raplace (..) to number (..), should matches without brace pattern
// without brace pattern
static Pattern numberPattern = Pattern.compile("[+\\-]?(([0-9]+\\.[0-9]+)|([0-9]+\\.?)|(\\.?[0-9]+))([+\\-/*](([0-9]+\\.[0-9]+)|([0-9]+\\.?)|(\\.?[0-9]+)))*");
static Pattern bracePattern = Pattern.compile("\\([^()]+\\)");
public static boolean matchesForMath(String txt) {
if (txt == null || txt.isEmpty()) return false;
txt = txt.replaceAll("\\s+", "");
if (!txt.contains("(") && !txt.contains(")")) return numberPattern.matcher(txt).matches();
if (txt.contains("(") ^ txt.contains(")")) return false;
if (txt.contains("()")) return false;
Queue<String> toBeRematch = new ArrayDeque<>();
toBeRematch.add(txt);
while (toBeRematch.size() > 0) {
String line = toBeRematch.poll();
Matcher m = bracePattern.matcher(line);
if (m.find()) {
String newline = line.substring(0, m.start()) + "1" + line.substring(m.end());
String withoutBraces = line.substring(m.start() + 1, m.end() - 1);
toBeRematch.add(newline);
if (!numberPattern.matcher(withoutBraces).matches()) return false;
}
}
return true;
}

How do I count odd and even amounts of characters with regular expressions?

I'm trying to pull out all strings which have an even number of B's and an odd number of C's. I have the regexes to match odd A's and even B's but I cannot get the two to work together. The strings are delimited by whitespace (tabs, newlines, spaces).
e.g.
XABBAC ABCDEBCC ABSDERERES ABBAAJSER HGABAA
I have for odd A's
\b[^A]*A([^A]*A[^A]*A)*[^A]*\b
And for even B's
\b[^B]*(B[^B]*B[^B]*)*[^B]*\b
I know I need to use +ve lookahead and have tried:
\b(?=[^A]*A([^A]*A[^A]*A)*[^A]*\b)[^B]*(B[^B]*B[^B]*)*[^B]*\b
but it doesn't work - does anybody know why?
The problem is that your regexes (regexen?) can match zero characters - \b\b will match on a single word boundary, and so will \b{someregexthatcanmatchzerocharacters}\b.
As Anon already mentioned: your pattern matches empty strings, causing m.find() to never advance in the target string. So, you need to let your even B's actually match Strings containing 2, 4, 6, ... number of B's. If you want, you can alternate between an even number of B's and this: [^B\\s]+ (which matches Strings containing 0 B's). As long as you actually match one or more character with it, then you should be okay.
Also, you don't want to look ahead and let the negated classes match spaces: that way you get too much matches.
Try something like this:
String text = "XABBAC ABCDEBCC ABSDERERES ABBAAJSER HGABAA";
String oddAs = "\\b[^A\\s]*A([^A\\s]*A[^A\\s]*A)*[^A\\s]*\\b";
String evenBs = "\\b([^B\\s]*(B[^B\\s]*B[^B\\s]*)+|[^B\\s]+)\\b";
Pattern p = Pattern.compile(String.format("(?=%s)(?=%s)\\S+", oddAs, evenBs));
Matcher m = p.matcher(text);
while (m.find()) {
System.out.println(m.group());
}
which produces:
ABCDEBCC
ABBAAJSER
With commons.lang.StringUtils it's even more concise:
String data = "XABBAC ABCDEBCC ABSDERERES ABBAAJSER HGABAA";
String[] items = data.split("\\s+");
for(String item: items ) {
if (countMatches(item, "B") % 2 == 0
&& countMatches(item, "C") % 2 != 0) {
System.out.println( item );
}
}
regex is overrated
String str = "XABBAC ABCDEBCC ABSDERERES ABBAAJSER HGABAA";
String[] s = str.split("\\s+");
for (int j=0 ;j< s.length;j++) {
int countC=0 ;
int countB=0;
for(int i=0;i<s[j].length();i++){
char c = s[j].charAt(i) ;
if (c == 'C') countC++;
if (c == 'B') countB++;
}
if ( (countC % 2) != 0 )
System.out.println( s[j] + " has odd C");
if ( (countB % 2) == 0 )
System.out.println( s[j] + " has even B");
}