Conditional regex replace in nodejs - javascript

I have an address like this:
117042,ABC DEF,HIJ KLMNOP,9,170
and want to have
117042,ABC DEF,HIJ KLMNOP 9 170
I tried it with this replace Regex
address = address.replace(/,[\d]/g, " ");
but this results in
117042,ABC DEF,HIJ KLMNOP 70
I do not want to replace the digit but still need to check if the digit comes after the comma to not match the other commas.
I am not very good with regex thats why I am asking for help.

You may only replace commas after numbers if they occur at the end of string:
var s = "117042,ABC DEF,HIJ KLMNOP,9,170";
var res = s.replace(/,(\d+)(?=(?:,\d+)*$)/g, " $1");
console.log(res);
The ,(\d+)(?=(?:,\d+)*$) regex matches:
, - a comma
(\d+) - (Group 1, referred to via $1 from the replacement pattern) one or more digits
(?=(?:,\d+)*$) - a positive lookahead that requires 0+ sequences of , + one or more digits at the end of the string.

Related

Formatting a phone number in specific way?

This is not a duplicate, the linked thread does not explain how to achieve this.
I'm looking to get a phone number in a specific format.
+xx (x) xxx xxx xxxx
Country code.
Space.
Zero in brackets.
Space.
3 digits.
Space.
3 digits.
Space.
4 digits.
The user could type anything in (but should always be a +61 number). So far I have tried the below.
Removing spaces and non numeric characters.
If starting with a zero, remove.
If starting with 610, remove.
If starting with 61, remove.
Re add country code in specific format and format rest of phone number is a 3,3,4 format.
My question, is - is there a way to simply the below to perhaps one expression?
value = value.replace(/\D/g,'');
value = value.startsWith(0) ? value.substring(1) : value;
value = value.startsWith('610') ? value.substring(3) : value;
value = value.startsWith('61') ? value.substring(2) : value;
value = '+61 (0) ' + value.replace(/\d{3,4}?(?=...)/g, '$& ');
To expand and explain on #splash58's comment they propose using two regular expressions to do the full replacement you desire. The first(/\D|(0+|610|61)/gi) will remove all unwanted characters within the string. The second (/(\d{3})(\d{3})(\d{4})/gi) will take the remaining digits and capture the desired groupings so you can format them as desired. I highly suggest looking at the regex101 links they provided as that site will fully explain how and why a given expressions matches what it does on the right.
Short version:
/\D|(0+|610|61)/gi will match any NON-digit character OR a string of 0s, "610" or "61". Replace this with nothing to remove
/(\d{3})(\d{3})(\d{4})/gi will match a string of 10 digits and capture groups, that's what the parentheses are, of 3 digits, 3 digits and 4 digits. These can be referenced in the replacement as identifiers $1, $2 and $3 according to their position.
Putting it all together:
// look in a string and return formatted phone number only
function phone(str) {
str = str.replace(/\D|(0+|610|61)/gi, '');
str = str.replace(/(\d{3})(\d{3})(\d{4})/gi, '+61 (0) $1 $2 $3');
return str;
}
console.log(phone('xgsh6101231231234vvajx'));
console.log(phone('+6101231231234'));
I would also recommend first doing a search on the entire input string for a series of numbers or whitespace so that you end up with less false positives. This can be done with a regular expression like /[\d\s]+/
You might match the number using:
^.*?\+?0*610?(\d{3})(\d{3})(\d{4})(?!\d).*$
Regex demo
And replace with:
+61 (0) $1 $2 $3
Explanation
^ Assert the start of the string
.*? Match 0+ characters non greedy
\+? Match an optional plus sign
0*610? Match 0+ times a zero, 61 with optional zero
(\d{3})(\d{3})(\d{4}) match 3 groups with 3, 3, and 4 digits
(?!\d) Negative lookahead to assert what follows is not a digit
.* Match 0+ characters
$ Assert the end of the string
const strings = [
"xgsh6101231231234vvajx",
"xgsh06101231231234vvajx",
"xgsh000006101231231234vvajx",
"+6101231231234",
"xgsh61012312312345vvajx",
"xgsh5101231231234vvajx",
"xgsh00000101231231234vvajx",
"xgsh6143545626455345601231231234vvajx"
];
let pattern = /^.*?\+?0*610?(\d{3})(\d{3})(\d{4})(?!\d).*$/;
strings.forEach((s) => {
console.log(s.replace(pattern, "+61 (0) $1 $2 $3"));
});

Javascript Regex: negative lookbehind

I am trying to replace in a formula all floating numbers that miss the preceding zero. Eg:
"4+.5" should become: "4+0.5"
Now I read look behinds are not supported in JavaScript, so how could I achieve that? The following code also replaces, when a digit is preceding:
var regex = /(\.\d*)/,
formula1 = '4+1.5',
formula2 = '4+.5';
console.log(formula1.replace(regex, '0$1')); //4+10.5
console.log(formula2.replace(regex, '0$1')); //4+0.5
Try this regex (\D)(\.\d*)
var regex = /(\D)(\.\d*)/,
formula1 = '4+1.5',
formula2 = '4+.5';
console.log(formula1.replace(regex, '$10$2'));
console.log(formula2.replace(regex, '$10$2'));
You may use
s = s.replace(/\B\.\d/g, '0$&')
See the regex demo.
Details
\B\. - matches a . that is either at the start of the string or is not preceded with a word char (letter, digit or _)
\d - a digit.
The 0$& replacement string is adding a 0 right in front of the whole match ($&).
JS demo:
var s = "4+1.5\n4+.5";
console.log(s.replace(/\B\.\d/g, '0$&'));
Another idea is by using an alternation group that matches either the start of the string or a non-digit char, capturing it and then using a backreference:
var s = ".4+1.5\n4+.5";
console.log(s.replace(/(^|\D)(\.\d)/g, '$10$2'));
The pattern will match
(^|\D) - Group 1 (referred to with $1 from the replacement pattern): start of string (^) or any non-digit char
(\.\d) - Group 2 (referred to with $2 from the replacement pattern): a . and then a digit

javascript regex to check if first and last character are similar?

Is there any simple way to check if first and last character of a string are the same or not, only with regex?
I know you can check with charAt
var firstChar = str.charAt(0);
var lastChar = str.charAt(length-1);
console.log(firstChar===lastChar):
I'm not asking for this : Regular Expression to match first and last character
You can use regex with capturing group and its backreference to assert both starting and ending characters are same by capturing the first caharacter. To test the regex match use RegExp#test method.
var regex = /^(.).*\1$/;
console.log(
regex.test('abcdsa')
)
console.log(
regex.test('abcdsaasaw')
)
Regex explanation here :
^ asserts position at start of the string
1st Capturing Group (.)
.* matches any character (except newline) - between zero and unlimited times, as many times as possible, giving back as needed (greedy)
\1 matches the same text as most recently matched by the 1st capturing group
$ asserts position at the end of the string
The . doesn't include newline character, in order include newline update the regex.
var regex = /^([\s\S])[\s\S]*\1$/;
console.log(
regex.test(`abcd
sa`)
)
console.log(
regex.test(`ab
c
dsaasaw`)
)
Refer : How to use JavaScript regex over multiple lines?
Regex explanation here :
[.....] - Match a single character present
\s - matches any whitespace character (equal to [\r\n\t\f\v ])
\S - matches any non-whitespace character (equal to [^\r\n\t\f ])
finally [\s\S] is matches any character.
You can try it
const rg = /^([\w\W]+)[\w\W]*\1$/;
console.log(
rg.test(`abcda`)
)
console.log(
rg.test(`aebcdae`)
)
console.log(
rg.test(`aebcdac`)
)
var rg = /^([a|b])([a|b]+)\1$|^[a|b]$/;
console.log(rg.test('aabbaa'))
console.log(rg.test('a'))
console.log(rg.test('b'))
console.log(rg.test('bab'))
console.log(rg.test('baba'))
This will make sure that characters are none other than a and b which have the same start and end.
It will also match single characters because they too start and end with same character.

split javascript string using a regexp to separate numbers from other characters

so for example:
"10.cm" ...becomes... [10,".cm"] or ["10",".cm"], either will do as I can work with a string once it's split up.
i tried
"10.cm".split(/[0-9]/|/[abc]/)
but it seems that i don't have such a great understanding of using regexp's
thanks
You may tokenize the string into digits and non-digits with /\d+|\D+/g regex:
var s = "10.cm";
console.log(s.match(/\d+|\D+/g));
Details:
\d+ - matches 1 or more digits
| - or
\D+ - matches 1 or more characters other than digits.
/\W/ Matches any non-word character. This includes spaces and punctuation, but not underscores. In this solution can be used /\W/ with split and join methods. You can separate numbers from other characters.
let s = "10.cm";
console.log(s.split(/\W/).join(" "));
output = 10 cm

Regexp match spaces not followed be a specific word

I have spent the last couple of hours trying to figure out how to match all whitespace (\s) unless followed by AND\s or preceded by \sAND.
I have this so far
\s(?!AND\s)
but it is then matching the space after \sAND, but I don't want that.
Any help would be appreciated.
Often, when you want to split by a single character that appears in specific context, you can replace the approach with a matching one.
I suggest matching all sequences of non-whitespace characters joined with AND enclosed with whitespace ones before and then match any other non-whitespace sequences. Thus, we'll ensure we get an array of necessary substrings:
\S+\sAND\s\S+|\S+
See regex demo
I assume the \sAND\s pattern appears between some non-whitespace characters.
var re = /\S+\sAND\s\S+|\S+/g;
var str = 'split this but don\'t split this AND this';
var res = str.match(re);
document.write(JSON.stringify(res));
As Alan Moore suggests, the alternation can be unrolled into \S+(?:\sAND\s\S+)*:
\S+ - 1 or more non-whitespace characters
(?:\sAND\s\S+)* - 0 or more (thus, it is optional) sequences of...
\s - one whitespace (add + to match 1 or more)
AND - literal AND character sequence
\s - one whitespace (add + to match 1 or more)
\S+ - one or more non-whitespace symbols.
Since JS doesn't support lookbehinds, you can use the following trick:
Match (\sAND\s)|\s
Throw away any match where $1 has a value
Here's a short example which replaces the spaces you want with an underscore:
var str = "split this but don't split this AND this";
str = str.replace(/(\sAND\s)|\s/g, function(m, a) {
return a ? m : "_";
});
document.write(str);

Categories