I have this regex that should match when there's two numbers in brackets
/(P|C\(\d+\,{0,1}\s*\d+\))/g
for example:
C(1, 2) or P(2 3) //expected to match
C(43) or C(43, ) // expect not to match
but it also matches the ones with only 1 number, how can i fix it?
You have a couple of issues. Firstly, your regex will match either P on its own or C followed by numbers in parentheses; you should replace P|C with [PC] (you could use (?:P|C) but [PC] is more performant, see this Q&A). Secondly, since your regex makes both the , and spaces optional, it can match 43 without an additional number (the 4 matches the first \d+ and the 3 the second \d+). You need to force the string to either include a , or at least one space between the numbers. You can do that with this regex:
[PC]\(\d+[ ,]\s*\d+\)
Demo on regex101
Try this regex
[PC]\(\d+(?:,| +) *\d+\)
Click for Demo
Explanation:
[PC]\( - matches either P( or C(
\d+ - matches 1+ digits
(?:,| +) - matches either a , or 1+ spaces
*\d+ - matches 0+ spaces followed by 1+ digits
\) - matches )
You can relax the separator between the numbers by allowing any combination of command and space by using \d[,\s]+\d. Test case:
const regex = /[PC]\(\d+[,\s]+\d+\)/g;
[
'C(1, 2) or P(2 3)',
'C(43) or C(43, )'
].forEach(str => {
let m = str.match(regex);
console.log(str + ' ==> ' + JSON.stringify(m));
});
Output:
C(1, 2) or P(2 3) ==> ["C(1, 2)","P(2 3)"]
C(43) or C(43, ) ==> null
Your regex should require the presence of at least one delimiting character between the numbers.
I suppose you want to get the numbers out of it separately, like in an array of numbers:
let tests = [
"C(1, 2)",
"P(2 3)",
"C(43)",
"C(43, )"
];
for (let test of tests) {
console.log(
test.match(/[PC]\((\d+)[,\s]+(\d+)\)/)?.slice(1)?.map(Number)
);
}
Related
I have string "JHJK34GHJ456HJK". How to check if this string has both letter and number, doesn't have whitespace, doesn't have special characters like # - /, If has only letter or only number didn't match.
I try with regex below, result is true if string is only number or letter.
const queryLetterNumber = /^[A-Za-z0-9]*$/.test("JHJK34GHJ456HJK");
const input= [
'JHJK34GHJ456HJK',
'JHJKAAGHJAAAHJK',
'123456789012345',
'JHJK34 space JK',
'JHJK34$dollarJK'
];
const regex = /^(?=.*[0-9])(?=.*[A-Za-z])[A-Za-z0-9]+$/;
input.forEach(str => {
console.log(str + ' => ' + regex.test(str));
});
Output:
JHJK34GHJ456HJK => true
JHJKAAGHJAAAHJK => false
123456789012345 => false
JHJK34 space JK => false
JHJK34$dollarJK => false
Explanation:
^ - anchor at beginning
(?=.*[0-9]) - positive lookahead expecting at least one digit
(?=.*[A-Za-z]) - positive lookahead expecting at least one alpha char
[A-Za-z0-9]+ - expect 1+ alphanumeric chars
$ - anchor at end
you should use a regular expression to check for alphanumeric content in the string
/^[a-z0-9]+$/i
The above is a sample that checks for a-z and numbers from 0-9. however, review other options as given here
I am trying to remove all the characters from the string after comma except the first letter. The string is basically the last name,first name.
For example:
Smith,John
I tried as below but it removes comma and everything after comma.
let str = "Smith,John";
str = str.replace(/\s/g, ""); // to remove all whitespace if there is any at the beginning, in the middle and at the end
str = str.split(',')[0];
Expected output: Smith,J
Thank you!
Or try (,\w).* with replace:
let str = "Smith,John";
str = str.replace(/(,\w).*/, '$1');
console.log(str);
Try this regex out:
\w+,\w
This matches one or more characters before the comma and then matches only 1 character.
Here is the demo: https://regex101.com/r/bKpWt7/1
Note: \w matches any character from [a-zA-Z0-9_].
Taking optional spaces around the comma in to account, and perhaps multiple "names" before the comma:
*([^\s,][^,\n]*?) *, *([^\s,]).*
* Match optional spaces
( Capture group 1
*([^\s,] Match optional spaces and match at least a single char other than a whitespace char or a ,
[^,\n]*? Match any char except a , or a newline non greedy
) Close group 1
*, * Match a comma between optional spaces
([^\s,]) Capture group 2, match a single char other than , or a whitespace char
.* Match the rest of the line
Regex demo
In the replacement using group 1 and group 2 with a comma in between $1,$2
const regex = / *([^\s,][^,\n]*?) *, *([^\s,]).*/;
[
"Smith,John Jack",
"Smith Lastname , Jack John",
"Smith , John",
" ,Jack"
].forEach(s => console.log(s.replace(regex, "$1,$2")));
I have array of values which I have to separate by their uppercase. But there are some cases where the value of the array has 2, 3 or 4 serial uppercases that I must not separate. Here are some values:
ERISACheckL
ERISA404cCheckL
F401kC
DisclosureG
SafeHarborE
To be clear result must be:
ERISA Check L
ERISA 404c Check L
F 401k C
Disclosure G
Safe Harbor E
I tried using:
value.match(/[A-Z].*[A-Z]/g).join(" ")
But of couse it is not working for serial letters.
One option could be matching 1 or more uppercase characters asserting what is directly to the right is not a lowercase character, or get the position where what is on the left is a char a-z or digit, and on the right is an uppercase char.
The use split and use a capture group for the pattern to keep it in the result.
([A-Z]+(?![a-z]))|(?<=[\da-z])(?=[A-Z])
( Capture group 1 (To be kept using split)
[A-Z]+(?![a-z]) Match 1+ uppercase chars asserting what is directly to the right is a-z
) Close group 1
| Or
(?<=[\da-z])(?=[A-Z]) Get the postion where what is directly to left is either a-z or a digit and what is directly to the right is A-Z
Regex demo
const pattern = /([A-Z]+(?![a-z]))|(?<=[\da-z])(?=[A-Z])/;
[
"ERISACheckL",
"ERISA404cCheckL",
"F401kC",
"DisclosureG",
"SafeHarborE"
].forEach(s => console.log(s.split(pattern).filter(Boolean).join(" ")))
Another option is to use an alternation | matching the different parts:
[A-Z]+(?![a-z])|[A-Z][a-z]*|\d+[a-z]+
[A-Z]+(?![a-z]) Match 1+ uppercase chars asserting what is directly to the right is a-z
| Or
[A-Z][a-z]* Match A-Z optionally followed by a-z to also match single uppercase chars
| Or
\d+[a-z]+ match 1+ digits and 1+ chars a-z
Regex demo
const pattern = /[A-Z]+(?![a-z])|[A-Z][a-z]*|\d+[a-z]+/g;
[
"ERISACheckL",
"ERISA404cCheckL",
"F401kC",
"DisclosureG",
"SafeHarborE"
].forEach(s => console.log(s.match(pattern).join(" ")))
function formatString(str) {
return str.replace(/([A-Z][a-z]+|\d+[a-z]+)/g, ' $1 ').replace(' ', ' ').trim();
}
// test
[
'ERISACheckL',
'ERISA404cCheckL',
'F401kC',
'DisclosureG',
'SafeHarborE'
].forEach(item => {
console.log(formatString(item));
});
I've being trying to generate a regex for this string:
case1: test-123456789 should get 56789
case2: test-1234-123456789 should get 56789
case3: test-12345 should fail or not giving anything
what I need is a way to get only the last 5 numbers from only 9 numbers
so far I did this:
case.match(/\d{5}$/)
it works for the first 2 cases but not for the last one
You may use
/\b\d{4}(\d{5})$/
See the regex demo. Get Group 1 value.
Details
\b - word boundary (to make sure the digit chunks are 9 digit long) - if your digit chunks at the end of the string can contain more, remove \b
\d{4} - four digits
(\d{5}) - Group 1: five digits
$ - end of string.
JS demo:
var strs = ['test-123456789','test-1234-123456789','test-12345'];
var rx = /\b\d{4}(\d{5})$/;
for (var s of strs) {
var m = s.match(rx);
if (m) {
console.log(s, "=>", m[1]);
} else {
console.log("Fail for ", s);
}
}
You can try this:
var test="test-123456789";
console.log((test.match(/[^\d]\d{4}(\d{5})$/)||{1: null/*default value if not found*/})[1]);
This way supports default value for when not found any matching (look at inserted comment inline above code.).
You can use a positive lookbehind (?<= ) to assert that your group of 5 digits is preceeded by a group of 4 digits without including them in the result.
/(?<=\d{4})\d{5}$/
var inputs = [
"test-123456789", // 56789
"test-1234-123456789", // 56789
"test-12345", //fail or not giving anything
]
var rgx = /(?<=\d{4})\d{5}$/
inputs.forEach(str => {
console.log(rgx.exec(str))
})
If I have an E.164 formatted phone number and I want to look up any users with that phone number, though their number may not be formatted, what would that regex look like?
Example:
Given:
+1234567891
Regex should match any of:
(123) 456 7891
123-456-7891
+1234567891
123.456.7891
1234567891
Any of the above with trailing or leading whitespace.
var str = '+1234567891',
parts = str.match(/\+((\d{3})(\d{3})(\d{4}))/).slice(1),
num = parts.shift(),
rg = new RegExp(
'\\s*(?:\\+?' + [
num,
parts.join('.'),
parts.join('-'),
'\\(' + parts[0] + '\\) ' + parts.slice(1).join(' ')
].join('|') + ')\\s*');
In this case, it will produce
/\s*(?:\+?1234567891|123.456.7891|123-456-7891|\(123\) 456 7891)\s*/
Try:
/\s*(\+)?(\(\d{3}\)|\d{3})([ -.]|)\d{3}(\3)\d{4}\s*/
See the regex101 example
How it works
\s* matches any preceding white space
(\+)? optionally matches +
(\(\d{3}\)|\d{3}) matches (123) or just 123
([ -.]|) matches , -, . or nothing
\d{3} matches 123
(\3) whatever was matches by ( |-|.|)
\d{4} match 1234
\s* matches any following white space
I think the best you can do is normalize both numbers and compare the result. You can, for example, remove everything that is not a number ([^0-9]) and compare only the digits left.
You can use following regex :
^\s?(\(\d{3}\)|\+?\d{3})([\s-.])?\d{3}\2\d{4}\s?$
Demo :https://www.regex101.com/r/jM2fF4/6