Dynamically split string using regex - javascript

I am receiving an Australian phone number from the user as a text input. The string will be 10 characters long and begin with 04. I want to split the string as the user is entering it so it turns out like 0411 111 111.
My current solution is value.toString().replace(/^(04\d{2})(\d{3})(\d{3})$/, $1 $2 $3)
This solution splits the string correctly, but only when the user has entered the entire 10 characters. I want it to start splitting after the first 4 characters have been entered ie 0411 1 etc.

Here is a one liner which will work for your exact use case:
var results = "0411111111".split(/(?=\d{6}$)|(?=\d{3}$)/);
console.log(results);
We may split your string on a regex which targets the point after 4 digits and the point after 7 digits.

Consider something like below that checks the length of the currently input mobile number and then applies a different regex depending on the length:
var mobileInput = document.getElementById('mobile');
mobileInput.addEventListener('keyup', foo);
function foo() {
var unformatted = mobileInput.value;
var pattern, replacer;
if (unformatted.length < 5) {
pattern = /(04\d{2})/;
replacer = '$1 ';
} else if (unformatted.length < 9) {
pattern = /(04\d{2})\s{1}(\d{3})/;
replacer = '$1 $2 ';
} else {
pattern = /^(04\d{2})(\d{3})(\d{3})$/;
replacer = '$1 $2 $3';
}
var formatted = unformatted.replace(pattern, replacer);
mobileInput.value = formatted;
}
<input type="text" id="mobile" />

I have managed to come up with a bit of a solution. It is not exactly what I was aiming for, but it does the job.
value.toString()
.replace(/^(04\d{2})(\d{3})(\d{3})$/, $1 $2 $3)
.replace(/[\s-]+$/, "")
This strips out the white space on each keypress (each time the regex is called) and reformats it.

here is my solution:
remove spaces added by before (to recover phone numbers from being splitted)
try to match input using a regex
combine matches and handle some other situations
code:
document.getElementById("phone").addEventListener("input", function() {
var matches = this.value.replace(/ /g, "").match(/^(04\d{2})(\d{3})?(\d{3})?(\d*?)$/);
this.value = matches && matches.length > 2 ?
matches.slice(1, matches.length - 1).join(" ")
+ (matches[matches.length - 1] || "")
: this.value;
});
<input id="phone" maxlength="12">

I'd probably do something like this:
let phone = document.getElementById('phone');
phone.addEventListener('keyup', evt => {
// get value, removing anything that isn't a number
let text = phone.value.replace(/\D/g, '');
// turn it into an array
text = text.split('');
// create a new array containing each group of digits, separated by spaces
let out = [...text.slice(0, 4), ' ', ...text.slice(4, 7), ' ', ...text.slice(7, 10)];
// turn it back into a string, remove any trailing spaces
phone.value = out.join('').trim();
}, false);
<input id="phone">

Related

Regex expression to get numbers without parentheses ()

I'm trying to create a regex that will select the numbers/numbers with commas(if easier, can trim commas later) that do not have a parentheses after and not the numbers inside the parentheses should not be selected either.
Used with the JavaScript's String.match method
Example strings
9(296,178),5,3(123),10
10,9(296,178),2,5,3(123),3(124,125)
10,7,5(296,293,444,1255),3(218),2,4
What i have so far:
/((^\d+[^\(])|(,\d+,)|(,*\d+$))/gm
I tried this in regex101 and underlined the numbers i would like to match and x on the one that should not.
You could start with a substitution to remove all the unwanted parts:
/\d*\(.*?\),?//gm
Demo
This leaves you with
5,10
10,2,5,
10,7,2,4
which makes the matching pretty straight forward:
/(\d+)/gm
If you want it as a single match expression you could use a negative lookbehind:
/(?<!\([\d,]*)(\d+)(?:,|$)/gm
Demo - and here's the same matching expression as a runnable javascript (skeleton code borrowed from Wiktor's answer):
const text = `9(296,178),5,3(123),10
10,9(296,178),2,5,3(123),3(124,125)
10,7,5(296,293,444,1255),3(218),2,4`;
const matches = Array.from(text.matchAll(/(?<!\([\d,]*)(\d+)(?:,|$)/gm), x=>x[1])
console.log(matches);
Here, I'd recommend the so-called "best regex trick ever": just match what you do not need (negative contexts) and then match and capture what you need, and grab the captured items only.
If you want to match integer numbers that are not matched with \d+\([^()]*\) pattern (a number followed with a parenthetical substring), you can match this pattern or match and capture the \d+, one or more digit matching pattern, and then simply grab Group 1 values from matches:
const text = `9(296,178),5,3(123),10
10,9(296,178),2,5,3(123),3(124,125)
10,7,5(296,293,444,1255),3(218),2,4`;
const matches = Array.from(text.matchAll(/\d+\([^()]*\)|(\d+)/g), x=> x[1] ?? "").filter(Boolean)
console.log(matches);
Details:
text.matchAll(/\d+\([^()]*\)|(\d+)/g) - matches one or more digits (\d+) + ( (with \() + any zero or more chars other than ( and ) (with [^()]*) + \) (see \)), or (|) one or more digits captured into Group 1 ((\d+))
Array.from(..., x=> x[1] ?? "") - gets Group 1 value, or, if not assigned, just adds an empty string
.filter(Boolean) - removes empty strings.
Using several replacement regexes
var textA = `9(296,178),5,3(123),10
10,9(296,178),2,5,3(123),3(124,125)
10,7,5(296,293,444,1255),3(218),2,4
`
console.log('A', textA)
var textB = textA.replace(/\(.*?\),?/g, ';')
console.log('B', textB)
var textC = textB.replace(/^\d+|\d+$|\d*;\d*/gm, '')
console.log('C', textC)
var textD = textC.replace(/,+/g, ' ').trim(',')
console.log('D', textD)
With a loop
Here is a solution which splits the lines on comma and loops over the pieces:
var inside = false;
var result = [];
`9(296,178),5,3(123),10
10,9(296,178),2,5,3(123),3(124,125)
10,7,5(296,293,444,1255),3(218),2,4
`.split("\n").map(line => {
let pieceArray = line.split(",")
pieceArray.forEach((piece, k) => {
if (piece.includes('(')) {
inside = true
} else if (piece.includes(')')) {
inside = false
} else if (!inside && k > 0 && k < pieceArray.length-1 && !pieceArray[k-1].includes(')')) {
result.push(piece)
}
})
})
console.log(result)
It does print the expected result: ["5", "7"]

Intl.NumberFormat() constructor with phone numbers [duplicate]

I'm looking to reformat (replace, not validate - there are many references for validating) a phone number for display in Javascript. Here's an example of some of the data:
123 4567890
(123) 456-7890
(123)456-7890
123 456 7890
123.456.7890
(blank/null)
1234567890
Is there an easy way to use a regular expression to do this? I'm looking for the best way to do this. Is there a better way?
I want to reformat the number to the following: (123) 456-7890
Assuming you want the format "(123) 456-7890":
function formatPhoneNumber(phoneNumberString) {
var cleaned = ('' + phoneNumberString).replace(/\D/g, '');
var match = cleaned.match(/^(\d{3})(\d{3})(\d{4})$/);
if (match) {
return '(' + match[1] + ') ' + match[2] + '-' + match[3];
}
return null;
}
Here's a version that allows the optional +1 international code:
function formatPhoneNumber(phoneNumberString) {
var cleaned = ('' + phoneNumberString).replace(/\D/g, '');
var match = cleaned.match(/^(1|)?(\d{3})(\d{3})(\d{4})$/);
if (match) {
var intlCode = (match[1] ? '+1 ' : '');
return [intlCode, '(', match[2], ') ', match[3], '-', match[4]].join('');
}
return null;
}
formatPhoneNumber('+12345678900') // => "+1 (234) 567-8900"
formatPhoneNumber('2345678900') // => "(234) 567-8900"
Possible solution:
function normalize(phone) {
//normalize string and remove all unnecessary characters
phone = phone.replace(/[^\d]/g, "");
//check if number length equals to 10
if (phone.length == 10) {
//reformat and return phone number
return phone.replace(/(\d{3})(\d{3})(\d{4})/, "($1) $2-$3");
}
return null;
}
var phone = '(123)4567890';
phone = normalize(phone); //(123) 456-7890
var x = '301.474.4062';
x = x.replace(/\D+/g, '')
.replace(/(\d{3})(\d{3})(\d{4})/, '($1) $2-$3');
alert(x);
This answer borrows from maerics' answer. It differs primarily in that it accepts partially entered phone numbers and formats the parts that have been entered.
phone = value.replace(/\D/g, '');
const match = phone.match(/^(\d{1,3})(\d{0,3})(\d{0,4})$/);
if (match) {
phone = `${match[1]}${match[2] ? ' ' : ''}${match[2]}${match[3] ? '-' : ''}${match[3]}`;
}
return phone
I'm using this function to format US numbers.
function formatUsPhone(phone) {
var phoneTest = new RegExp(/^((\+1)|1)? ?\(?(\d{3})\)?[ .-]?(\d{3})[ .-]?(\d{4})( ?(ext\.? ?|x)(\d*))?$/);
phone = phone.trim();
var results = phoneTest.exec(phone);
if (results !== null && results.length > 8) {
return "(" + results[3] + ") " + results[4] + "-" + results[5] + (typeof results[8] !== "undefined" ? " x" + results[8] : "");
}
else {
return phone;
}
}
It accepts almost all imaginable ways of writing a US phone number. The result is formatted to a standard form of (987) 654-3210 x123
thinking backwards
Take the last digits only (up to 10) ignoring first "1".
function formatUSNumber(entry = '') {
const match = entry
.replace(/\D+/g, '').replace(/^1/, '')
.match(/([^\d]*\d[^\d]*){1,10}$/)[0]
const part1 = match.length > 2 ? `(${match.substring(0,3)})` : match
const part2 = match.length > 3 ? ` ${match.substring(3, 6)}` : ''
const part3 = match.length > 6 ? `-${match.substring(6, 10)}` : ''
return `${part1}${part2}${part3}`
}
example input / output as you type
formatUSNumber('+1333')
// (333)
formatUSNumber('333')
// (333)
formatUSNumber('333444')
// (333) 444
formatUSNumber('3334445555')
// (333) 444-5555
2021
libphonenumber-js
Example
import parsePhoneNumber from 'libphonenumber-js'
const phoneNumber = parsePhoneNumber('+12133734253')
phoneNumber.formatInternational() === '+1 213 373 4253'
phoneNumber.formatNational() === '(213) 373-4253'
phoneNumber.getURI() === 'tel:+12133734253'
Based on David Baucum's answer - here is a version that trys to improve auto-replacement "as you type" for example in a React onChange event handler:
function formatPhoneNumber(phoneNumber) {
const cleanNum = phoneNumber.toString().replace(/\D/g, '');
const match = cleanNum.match(/^(\d{3})(\d{0,3})(\d{0,4})$/);
if (match) {
return '(' + match[1] + ') ' + (match[2] ? match[2] + "-" : "") + match[3];
}
return cleanNum;
}
//...
onChange={e => setPhoneNum(formatPhoneNumber(e.target.value))}
It will insert (###) as soon as there are 3 numbers and then it will keep following the RegEx until it looks like this (###) ###-####
I've extended David Baucum's answer to include support for extensions up to 4 digits in length. It also includes the parentheses requested in the original question. This formatting will work as you type in the field.
phone = phone.replace(/\D/g, '');
const match = phone.match(/^(\d{1,3})(\d{0,3})(\d{0,4})(\d{0,4})$/);
if (match) {
phone = `(${match[1]}${match[2] ? ') ' : ''}${match[2]}${match[3] ? '-' : ''}${match[3]}${match[4] ? ' x' : ''}${match[4]}`;
}
return phone;
Almost all of these have issues when the user tries to backspace over the delimiters, particularly from the middle of the string.
Here's a jquery solution that handles that, and also makes sure the cursor stays in the right place as you edit:
//format text input as phone number (nnn) nnn-nnnn
$('.myPhoneField').on('input', function (e){
var $phoneField = e.target;
var cursorPosition = $phoneField.selectionStart;
var numericString = $phoneField.value.replace(/\D/g, '').substring(0, 10);
// let user backspace over the '-'
if (cursorPosition === 9 && numericString.length > 6) return;
// let user backspace over the ') '
if (cursorPosition === 5 && numericString.length > 3) return;
if (cursorPosition === 4 && numericString.length > 3) return;
var match = numericString.match(/^(\d{1,3})(\d{0,3})(\d{0,4})$/);
if (match) {
var newVal = '(' + match[1];
newVal += match[2] ? ') ' + match[2] : '';
newVal += match[3] ? '-' + match[3] : '';
// to help us put the cursor back in the right place
var delta = newVal.length - Math.min($phoneField.value.length, 14);
$phoneField.value = newVal;
$phoneField.selectionEnd = cursorPosition + delta;
} else {
$phoneField.value = '';
}
})
var numbers = "(123) 456-7890".replace(/[^\d]/g, ""); //This strips all characters that aren't digits
if (numbers.length != 10) //wrong format
//handle error
var phone = "(" + numbers.substr(0, 3) + ") " + numbers.substr(3, 3) + "-" + numbers.substr(6); //Create format with substrings
Here is one that will accept both phone numbers and phone numbers with extensions.
function phoneNumber(tel) {
var toString = String(tel),
phoneNumber = toString.replace(/[^0-9]/g, ""),
countArrayStr = phoneNumber.split(""),
numberVar = countArrayStr.length,
closeStr = countArrayStr.join("");
if (numberVar == 10) {
var phone = closeStr.replace(/(\d{3})(\d{3})(\d{4})/, "$1.$2.$3"); // Change number symbols here for numbers 10 digits in length. Just change the periods to what ever is needed.
} else if (numberVar > 10) {
var howMany = closeStr.length,
subtract = (10 - howMany),
phoneBeginning = closeStr.slice(0, subtract),
phoneExtention = closeStr.slice(subtract),
disX = "x", // Change the extension symbol here
phoneBeginningReplace = phoneBeginning.replace(/(\d{3})(\d{3})(\d{4})/, "$1.$2.$3"), // Change number symbols here for numbers greater than 10 digits in length. Just change the periods and to what ever is needed.
array = [phoneBeginningReplace, disX, phoneExtention],
afterarray = array.splice(1, 0, " "),
phone = array.join("");
} else {
var phone = "invalid number US number";
}
return phone;
}
phoneNumber("1234567891"); // Your phone number here
For all international Phone numbers with country code upto 3 digits, we can change the original answer a little bit as below.
For first match instead of looking for '1' we should look for 1-3 digits.
export const formatPhoneNumber = (phoneNumberString) => {
var cleaned = ('' + phoneNumberString).replace(/\D/g, '');
var match = cleaned.match(/^(\d{1,3}|)?(\d{3})(\d{3})(\d{4})$/);
if (match) {
var intlCode = (match[1] ? `+${match[1]} ` : '');
return [intlCode, '(', match[2], ') ', match[3], '-', match[4]].join('');
}
return null;
}
console.log( formatPhoneNumber('16464765278') )//+1 (646) 476-5278
console.log( formatPhoneNumber('+2549114765278')) //+254 (911) 476-5278
console.log( formatPhoneNumber('929876543210') )//+92 (987) 654-3210
Fulfils my requirement.
For US Phone Numbers
/^\(?(\d{3})\)?[- ]?(\d{3})[- ]?(\d{4})$/
Let’s divide this regular expression in smaller fragments to make is easy to understand.
/^\(?: Means that the phone number may begin with an optional (.
(\d{3}): After the optional ( there must be 3 numeric digits. If the phone number does not have a (, it must start with 3 digits. E.g. (308 or 308.
\)?: Means that the phone number can have an optional ) after first 3 digits.
[- ]?: Next the phone number can have an optional hyphen (-) after ) if present or after first 3 digits.
(\d{3}): Then there must be 3 more numeric digits. E.g (308)-135 or 308-135 or 308135
[- ]?: After the second set of 3 digits the phone number can have another optional hyphen (-). E.g (308)-135- or 308-135- or 308135-
(\d{4})$/: Finally, the phone number must end with four digits. E.g (308)-135-7895 or 308-135-7895 or 308135-7895 or 3081357895.
Reference :
http://www.zparacha.com/phone_number_regex/
You can use this functions to check valid phone numbers and normalize them:
let formatPhone = (dirtyNumber) => {
return dirtyNumber.replace(/\D+/g, '').replace(/(\d{3})(\d{3})(\d{4})/, '($1) $2-$3');
}
let isPhone = (phone) => {
//normalize string and remove all unnecessary characters
phone = phone.replace(/\D+/g, '');
return phone.length == 10? true : false;
}
The solutions above are superior, especially if using Java, and encountering more numbers with more than 10 digits such as the international code prefix or additional extension numbers. This solution is basic (I'm a beginner in the regex world) and designed with US Phone numbers in mind and is only useful for strings with just 10 numbers with perhaps some formatting characters, or perhaps no formatting characters at all (just 10 numbers). As such I would recomend this solution only for semi-automatic applications. I Personally prefer to store numbers as just 10 numbers without formatting characters, but also want to be able to convert or clean phone numbers to the standard format normal people and apps/phones will recognize instantly at will.
I came across this post looking for something I could use with a text cleaner app that has PCRE Regex capabilities (but no java functions). I will post this here for people who could use a simple pure Regex solution that could work in a variety of text editors, cleaners, expanders, or even some clipboard managers. I personally use Sublime and TextSoap. This solution was made for Text Soap as it lives in the menu bar and provides a drop-down menu where you can trigger text manipulation actions on what is selected by the cursor or what's in the clipboard.
My approach is essentially two substitution/search and replace regexes. Each substitution search and replace involves two regexes, one for search and one for replace.
Substitution/ Search & Replace #1
The first substitution/ search & replace strips non-numeric numbers from an otherwise 10-digit number to a 10-digit string.
First Substitution/ Search Regex: \D
This search string matches all characters that is not a digit.
First Substitution/ Replace Regex: "" (nothing, not even a space)
Leave the substitute field completely blank, no white space should exist including spaces. This will result in all matched non-digit characters being deleted. You should have gone in with 10 digits + formatting characters prior this operation and come out with 10 digits sans formatting characters.
Substitution/ Search & Replace #2
The second substitution/search and replace search part of the operation captures groups for area code $1, a capture group for the second set of three numbers $2, and the last capture group for the last set of four numbers $3. The regex for the substitute portion of the operation inserts US phone number formatting in between the captured group of digits.
Second Substitution/ Search Regex: (\d{3})(\d{3})(\d{4})
Second Substitution/ Replace Regex: \($1\) $2\-$3
The backslash \ escapes the special characters (, ) , (<-whitespace), and - since we are inserting them between our captured numbers in capture groups $1, $2, & $3 for US phone number formatting purposes.
In TextSoap I created a custom cleaner that includes the two substitution operation actions, so in practice it feels identical to executing a script. I'm sure this solution could be improved but I expect complexity to go up quite a bit. An improved version of this solution is welcomed as a learning experience if anyone wants to add to this.

Loop Function to find 14 digit numbers and run a script for those results - Javascript

Preface: I have two textareas. I want to paste a list of unformatted phone numbers to produce a list of phone numbers in a certain format. I figured out how to remove dashes, commas, spaces and letters to just produce the format I need. (I made it add a comma and a space and remove the last comma fyi)
Issue: The current code below works great in the order of the .replaces. I tried to group those together and it didn't work as well with some examples but breaking it up so it flows in that order seemed to work. However, I often have phone numbers of ranges. So if you have 555-555-5555 - 5556, it will output 55555555555556. 14 characters! I wondered if there was a way to "find" these 14 characters after this formula is ran and use another code I figured out (below the one below) to output the ranges for those numbers. I will post both codes below and finish my thought. Ideally, I want to combine both formulas.
<script language="javascript" type="text/javascript">
function textremv() {
let output = Array.from(
new Set(
document.getElementById("content").value
.replace(/,/g, "") // replace commas with nothing
.replace(/\n/g, ",\n") //replaces new lines with comma and new line
.replace(/\s|-/g, "") // replaces space and dash with nothing
.replace(/[{()}]/g,"") //replaces all special characters with nothing
.replace(/[a-zA-Z]/g, "") //replaces a-z with nothing
.replace(/,/g, ",\n") //replaces comma with comma linebreak
.split(',')
)
).join(", ");
document.getElementById("content2").innerHTML = output + " "; //adds space at the end
}
// [0-9]{10}-[0-9]{4}
}
function ct() {
/* Get the text field */
var copyText = document.getElementById("content2");
/* Select the text field */
copyText.select();
copyText.setSelectionRange(0, 99999); /*For mobile devices*/
/* Copy the text inside the text field */
document.execCommand("copy");
/* Alert the copied text */
alert("Copied the text: " + copyText.value);
/* <input type='button' value='Extract Text2' onclick='sortvalues(0);ct()'/> */
}
</script>
<form name="sorter">
<textarea rows='10' cols='20' id='content'></textarea>
<textarea rows='10' cols='20' id='content2'></textarea>
<input type='button' value='Extract Text' onclick='textremv();ct()'/>
</form>
<div id="output"></div>
Single range works with code below such as 5555555555-5556 will give both phone numbers listed out.
<script language="javascript" type="text/javascript">
function listrange(){
var range = document.getElementById("listrange1").value
var range1 = range.slice(0,10);
var range2 = range.slice(0,7) + range.slice(12,15);
var text = "";
var i = range1;
while (i <= range2) {
text += i + ", ";
i++;
}
document.getElementById("listrange2").innerHTML = text;
}
</script>
<textarea rows='10' cols='20' id='listrange1'></textarea>
<textarea rows='10' cols='20' id='listrange2'></textarea>
<input type='button' value='Extract Text' onclick='listrange()'/>
Summary: I'm not sure if there is a way to combine the formula to take those 14 characters and then run it against the second script I have there to produce the list of phone number ranges.
Example would be like this:
555-555-5555
123-456-7890-7891
555-555-5506
Should return an output of:
5555555555,
1234567890,
1234567891,
5555555506
I am just not sure how to make it retrospectively go back and look for those 14 characters to apply that loop function.
Thank you in advance!
Edit: Scott's answer worked!! In case you're coming across this question and are inexperienced as I am, here's the full code for you to play around with. This code assumes you are providing 10 digit phone numbers or 10 digits with a 4 digit range. Ex: 1234567890 or 1234567890-7899
<textarea rows='6' cols='50' id='listrange1'></textarea>
<textarea rows='6' cols='50' id='listrange2'></textarea>
<br>
<button id='extract' >Extract Phone Numbers</button>
<script type="text/javascript">
const getRange = (str) => {
const [_, intro, start, end] = str .match (/(\d{6})(\d{4})(\d{4})/)
return Array.from({length: end - start + 1}, (__, i) => intro + String(+start + i).padStart(4, '0'))
}
const phoneNumbers = str =>
str .split (/[,\s]+/) // break on commas and/or spaces
.map (str => str .replace (/\D/g, '')) // remove non-digits
.filter (Boolean) // remove empties
.filter (str => str .length == 10 || str.length == 14)
.flatMap (str => str .length == 14 ? getRange(str) : [str])
document.getElementById('extract').onclick = (evt) =>
document.getElementById('listrange2').innerHTML =
phoneNumbers(document.getElementById('listrange1').value).join('\n')
</script>
Searchable keywords: Javascript, phone number, ranges, phone number range, client-side, loop
Here is a version that didn't really look at your code but wrote it from scratch:
const getRange = (str) => {
const [_, intro, start, end] = str .match (/(\d{6})(\d{4})(\d{4})/)
return Array.from(
{length: end - start + 1},
(__, i) => intro + String(+start + i).padStart(4, '0')
)
}
const phoneNumbers = str =>
str .split (/[,\s]+/) // break on commas and/or spaces
.map (str => str .replace (/\D/g, '')) // remove non-digits
.filter (Boolean) // remove empties
.filter (str => str .length == 10 || str.length == 14)
.flatMap (str => str .length == 14 ? getRange(str) : [str])
const text = `First is 555-555-5555, more here: 123-456-7890-7893,
and a range starting at 0: 555-666-0000-0004
and another two: 555-555-5506 and 202-456-1414`
// ^-- (White House switchboard, if you need it)
console .log (phoneNumbers (text))
getRange takes a 14-digit string and creates all the phone numbers in the range. (There is no error-checking that the end of the range is higher than the beginning; you might want to add that.)
phoneNumbers breaks the string into chunks at spaces characters and commas, removes all non-digit characters from each resulting string, removes any strings that are now empty, and then uses getRange for the 14-digits ones. It uses flatMap to take the plain phone numbers and the arrays of them returned by getRange and flatten them into a single list.
You might want to do a further filter to remove the numbers that aren't of length 10 or 14. That would probably go right before the flatMap call.
Update: use with text areas
This captures the information in one text area and extracts the phone numbers when the button is pressed:
const getRange = (str) => {
const [_, intro, start, end] = str .match (/(\d{6})(\d{4})(\d{4})/)
return Array.from(
{length: end - start + 1},
(__, i) => intro + String(+start + i).padStart(4, '0')
)
}
const phoneNumbers = str =>
str .split (/[,\s]+/) // break on commas and/or spaces
.map (str => str .replace (/\D/g, '')) // remove non-digits
.filter (Boolean) // remove empties
.filter (str => str .length == 10 || str.length == 14)
.flatMap (str => str .length == 14 ? getRange(str) : [str])
document.getElementById('extract').onclick = (evt) =>
document.getElementById('listrange2').innerHTML =
phoneNumbers(document.getElementById('listrange1').value).join('\n')
<button id='extract' style="float:right">Extract Phone Numbers</button>
<textarea rows='6' cols='50' id='listrange1'>First is 555-555-5555,
more here: 123-456-7890-7893,
and another two: 555-555-5506 and 202-456-1414
and a range starting at 0: 555-666-0000-0004</textarea>
<textarea rows='6' cols='50' id='listrange2'></textarea>

Get number(decimal digit) from String

I see somebody already asked this question but the result is not really in the case of number is decimal digit.
Example:
var str = "textsometext13.523 after text";
Then if I use str.replace(/[^0-9]/gi, '');
It will return 13523 instead of 13.523
How I can use new regex to get it?
Thank you very much.
If you know your input string will only contain one number and not have a full stop at the end then simply update your regex to include a . in the list of characters to keep:
/[^0-9.]/gi
But if you need to allow for input like the following:
"text 123.12 text 13"
"The numbers are 132.12, 144.11, and 123.1."
...then you should use the .match() method, which with the right regex will return an array of matched numbers (or return null if there were no matches):
var results = input.match(/\d+(?:\.\d+)?/g);
That is, match one or more digits \d+, that are optionally followed by a decimal \. and one or more digits \d+.
Demo:
console.log( "text 123.12 text".match(/\d+(?:\.\d+)?/g) );
console.log( "The numbers are 132.12, 5, and 123.1.".match(/\d+(?:\.\d+)?/g) );
console.log( "No numbers".match(/\d+(?:\.\d+)?/g) );
You can use RegExp /\d+\.\d+|\d+/g to match digits followed by . character followed by digits, or one or more digits
str.match(/\d+\.\d+|\d+/g)
You can try this one:
var string = "textsometext13.523 after text";
var number = string.match(/[\d\.]+/).toString();
var num = number.split('.');
alert(num[1]); //display the numbers after the period(.) symbol
simply use like this /\d+(?:\.\d+)?/g:
console.log("textsometext13.523 after text".match(/\d+(?:\.\d+)?/g,""))
Alternate, its the reverse process replace the [a-z] same thing will append
console.log("textsometext13.523 after text".replace(/[a-z]/g,""))
This regex should match any number whether it has a decimal or not:
/(\d*\.?\d*)/g
SNIPPET
var btn1 = document.getElementById('btn1');
var inp1 = document.getElementById('inp1');
var out1 = document.getElementById('out1');
btn1.onclick = function() {
var str = inp1.value
var res = str.match(/\d*\.?\d*/g);
out1.innerHTML = res;
}
<input id='inp1'>
<input id='btn1' type='button' value='Extract Numbers'>
<output id='out1'></output>

Regex: Matching the first letter(s) of multiple words

So I am really bad at regex stuff ... I googled for an hour now and the best answer I could find is this one.
But I still can't for the sake of me figure it out ...
What I need is the following:
I have a JS array I need to .filter(). This arrays contains for example:
[ 'Gurken halbiert 2kg', 'Karotten geschnitten 5kg', 'Gurken RW' ]
For example: All of the following inputs should match the first entry ("Gurken halbiert 2kg"):
"Gu ha"
"gur h"
"gu halbi"
The following inputs should not match it:
"ken halbi"
"urk ha"
"gur biert"
Why? because one or more letters at the beginning of any word are missing.
More example inputs and the entries they should match:
input: "Gur" -> matches 1st and 3rd entry
input: "Kar g 5" -> matches 2nd
input: "G r" -> matches 3rd
I really hope someone can help as I am totally lost in this RegEx chaos - I never really understood them or how to use them.
Since the input varies, you would need to dynamically generate the regular expression.
In the function below, you will notice that we are basically building a string and then creating the regular expression using new RegExp(string, 'i').
The expression starts with a caret, and then basically follows the pattern:
^[[nth input char(s)]]\w*\s+[[nth input char(s)]]\w*\s+[[nth input char(s)]]\w*
It's worth pointing out that \w* is added after each input string and \s+ is added if it's not the last input string (i.e., not the end).
function generateRegex (input) {
var string = '^', arr = input.trim().split(' ');
arr.forEach(function (chars, i) {
string += chars + '\\w*' + (arr.length - 1 > i ? '\\s+' : '');
});
return new RegExp(string, 'i');
}
Then you can use the .filter() method on your array and return the elements that match:
var array = ['Gurken halbiert 2kg', 'Karotten geschnitten 5kg', 'Gurken RW'];
var filteredArray = array.filter(function (value) {
return value.match(generateRegex('Gur Ha'));
});
Output:
'Gur Ha' would match: ["Gurken halbiert 2kg"]
'Gur' would match: ["Gurken halbiert 2kg", "Gurken RW"]
'Kar g 5' would match: ["Karotten geschnitten 5kg"]
'G r' would match: ["Gurken RW"]
Example:
function generateRegex (input) {
var string = '^', arr = input.trim().split(' ');
arr.forEach(function (chars, i) {
string += chars + '\\w*' + (arr.length - 1 > i ? '\\s+' : '');
});
return new RegExp(string, 'i');
}
var array = ['Gurken halbiert 2kg', 'Karotten geschnitten 5kg', 'Gurken RW'];
var filteredArray = array.filter(function (value) {
return value.match(generateRegex('Gur'));
});
document.body.textContent = JSON.stringify(filteredArray);
Here is an example of how to filter user input as specified.
Notes
Escaping of regular expression characters from user input pattern (always sanitise user input).
Explicitly not using "\w" in order to support characters like "é".
Supports white space characters other than <space> like <tab> which can be copied and pasted into user input fields causing the user to think it's broken.
function doSubmit() {
// Get the user input search pattern string
var userInput = document.getElementById("myinput").value,
// List of strings to search
testList = [
'Gurken halbiert 2kg',
'Karotten geschnitten 5kg',
'Gurken RW'
],
// Between our "words" we allow zero or more non-space characters "[^\s]*"
// (this eats any extra characters the user might not have specified in their search pattern)
// followed by one or more white-space characters "\s+"
// (eating that space between the "words")
// Note that we are escaping the "\" characters here.
// Note we also don't use "\w" as this doesn't allow for characters like "é".
regexBetween = '[^\\s]*\\s+',
// Match the start of the string "^"
// Optionally allow one or more "words" at the start
// (this eats a "word" followed by a space zero or more times).
// Using an empty string here would allow "o g" to match the 2nd item in our test array.
regexStart = '^(?:' + regexBetween + ')*',
// Clean whitespace at begining and end
regexString = userInput.trim()
// Escape any characters that might break a regular expression
// Taken from: https://developer.mozilla.org/en/docs/Web/JavaScript/Guide/Regular_Expressions
.replace(/[.*+?^${}()|[\]\\]/g, "\\$&")
// Split into array of "words"
.split(/\s+/)
// Combine the "words" building our regular expression string
.join(regexBetween),
// Create the regular expression from the string (non-case-sensitive 'i')
regexObject = new RegExp(regexStart + regexString, 'i'),
// Filter the input array testing for matches against the regular expression.
resultsList = testList.filter(function(item) {
return regexObject.test(item);
});
// Ouput the array into the results text area, one per line.
document.getElementById('output').value = resultsList.join('\n') + '\n===the end===';
}
<form id="myform" onsubmit="doSubmit(); return false;">
<input type="text" id="myinput" value="" />
<input type="submit" name="submit" />
</form>
<textarea id="output" rows="5" cols="30">
</textarea>

Categories