Having a string like this
str = "word 12 otherword(s) 2000 19"
or like this
str = "word word 12 otherword(s) 2000 19"
I need to split the string in two, in order to have an array like this:
newstr[0] = first part of the string (i.e. "word" in the first case, "word word" in the second case);
newstr[1] = rest of the string (i.e. "12 otherword(s) 2000 19" in both cases).
I've tried to accomplish this using split and regex, without success:
str.split(/\d.*/) returns Array [ "word ", "" ] or Array [ "word word ", "" ]
while str.split(/^\D*/gm) returns Array [ "", "12 otherword(s) 2000 19" ]
Would you give me a suggestion? Even without using split and regex - if there's a better/faster (Vanilla JavaScript) solution.
There's 3 things going on here.
String.split usually doesn't includes the matched delimiter in the return array. So splitting abc.split('b') would return ['a', 'c']. This behavior can be changed by using a matching regex group; i.e. adding parens 'abc'.split(/(b)/) will return ['a', 'b', 'c'].
String.split will keep the delimter seperate from the other elements. I.e. 'abc'.split(/(b)/) will return 3 elements ['a', 'b', 'c']. Suffix the regex with .* to combine the last 2 elements: 'abc'.split(/(b.*)/) will return ['a', 'bc', ''].
Lastly, to ignore the last empty element, we send the 2nd param of 2.
let str = "word word 12 otherword(s) 2000 19";
let splitStr = str.split(/(\d.*)/, 2);
console.log(splitStr);
You can match these parts:
const strs = ["word 12 otherword(s) 2000 19", "word word 12 otherword(s) 2000 19"];
for (var s of strs) {
const [_, part1, part2] = s.match(/^(\D*)(\d+[\w\W]*)/)
console.log([part1, part2])
}
See the regex demo.
Regex details:
^ - start of a string
(\D*) - Group 1: any zero or more chars other than digits
(\d+[\w\W]*) - Group 2: one or more digits, and then any zero or more chars as many as possible.
Note you may .trim() the resulting parts when using them (print them with console.log([part1.trim(), part2.trim()])).
Related
I have string like as "1 + 2 - 3 + 10".
I want split it to "1", "+2", "-3", "+10".
Here is my code.
var expression = "1 + 2 - 3 + 10";
expression = expression.replace(/\s+/g, '');
let fields = expression.split(/([+-]\d+)/g);
console.log(fields);
But result is
["1", "+2", "", "-3", "", "+10", ""]
How can I make result ["1", "+2", "-3", "+10"]?
Your regular expression takes a group
/([+-]\d+)/
^ ^ group
which is included in the result set.
as result you get for each following iteration two parts, the part previous from the group and the group itself.
"1" first find
"+2" group as separator for splitting, included to result set
"" second find, empty because of the found next separator
"-3" second separator/group
"" third part without separator
"+10" third separator
"" rest part between separator and end of string
You could split with a positive lookahead of an operator.
const
string = '1 + 2 - 3 + 10',
result = string.replace(/\s+/g, '').split(/(?=[+-])/);
console.log(result);
I would handle this by first stripping off all whitespace, then using match() with the regex pattern [/*+-]?\d+, which will match all digits, with an optional leading operator (not present for the first term).
var input = "1 + 2 - 3 + 10";
var matches = input.replace(/\s+/g, '').match(/[/*+-]?\d+/g);
console.log(matches);
Example strings :
2222
333333
12345
111
123456789
12345678
Expected result:
2#222
333#333
12#345
111
123#456#789
12#345#678
i.e. '#' should be inserted at the 4th,8th,12th etc last position from the end of the string.
I believe this can be done using replace and some other methods in JavaScript.
for validation of output string i have made the regex :
^(\d{1,3})(\.\d{3})*?$
You can use this regular expression:
/(\d)(\d{3})$/
this will match and group the first digit \d and group the last three \d{3} which are then grouped in their own group. Using the matched groups, you can then reference them in your replacement string using $1 and $2.
See example below:
const transform = str => str.replace(/(\d)(\d{3})$/, '$1#$2');
console.log(transform("2222")); // 2#222
console.log(transform("333333")); // 333#333
console.log(transform("12345")); // 12#345
console.log(transform("111")); // 111
For larger strings of size N, you could use other methods such as .match() and reverse the string like so:
const reverse = str => Array.from(str).reverse().join('');
const transform = str => {
return reverse(reverse(str).match(/(\d{1,3})/g).join('#'));
}
console.log(transform("2222")); // 2#222
console.log(transform("333333")); // 333#333
console.log(transform("12345")); // 12#345
console.log(transform("111")); // 111
console.log(transform("123456789")); // 123#456#789
console.log(transform("12345678")); // 12#345#678
var test = [
'111',
'2222',
'333333',
'12345',
'123456789',
'1234567890123456'
];
console.log(test.map(function (a) {
return a.replace(/(?=(?:\B\d{3})+$)/g, '#');
}));
You could match all the digits. In the replacement insert an # after every third digit from the right using a positive lookahead.
(?=(?:\B\d{3})+$)
(?= Positive lookahead, what is on the right is
(?:\B\d{3})+ Repeat 1+ times not a word boundary and 3 digits
$ Assert end of string
) Close lookahead
Regex demo
const regex = /^\d+$/;
["2222",
"333333",
"12345",
"111",
"123456789",
"12345678"
].forEach(s => console.log(
s.replace(/(?=(?:\B\d{3})+$)/g, "#")
));
I have the following string patterns which I need to match as described.
I need only the first char/digit on each of the following examples. Before the '/' and after any space:
12/5 <--match on 1
x23/4.5 match on x
234.5/7 match on 2
2 - 012.3/4 match on 0
regex something like the following is obviously not enough:
\d(?=\d\/))
To make Clear
I'm actauly using the regex with js split so it's some mpping function which takes each one of the strings and split it on the match. So for example 2 - 012.3/4 would be split to [ 2 - 0, 12.3/4] and 12/5 to 1, [2/5] and so on.
See example (with non working regex) here:
https://regex101.com/r/N1RbGp/1
Try a regular expression like this:
(?<=^|\s)[a-zA-Z0-9](?=[^\s]*[/])
Breaking it down:
(?<=^|\s) is a zero-width (non-capturing) positive lookbehind that ensures
that the match will begin only immediately following start-of-text or a
whitespace character.
[a-zA-Z0-9] matches a single letter or digit.
(?=\S*[/]) is a zero-width (non-capturing) positive lookahead that requires
the matched letter or digit to be followed by zero or more non-whitespace characters and a solidus ('/') character.
Here's the code:
const texts = [
'12/5',
'x23/4.5',
'234.5/7',
'2 - 012.3/4',
];
texts.push( texts.join(', ') );
for (const text of texts) {
const rx = /(?<=^|\s)[a-zA-Z0-9](?=\S*[/])/g;
console.log('');
console.group(`text: '${text}'`);
for(let m = rx.exec(text) ; m ; m = rx.exec(text) ) {
console.log(`matched '${m[0]}' at offset ${m.index} in text.`);
}
console.groupEnd();
}
This is the output:
text: '12/5'
matched '1' at offset 0 in text.
text: 'x23/4.5'
matched 'x' at offset 0 in text.
text: '234.5/7'
matched '2' at offset 0 in text.
text: '2 - 012.3/4'
matched '0' at offset 4 in text.
text: '12/5, x23/4.5, 234.5/7, 2 - 012.3/4'
matched '1' at offset 0 in text.
matched 'x' at offset 6 in text.
matched '2' at offset 15 in text.
matched '0' at offset 28 in text.
The first group in this regex matches the character you're asking for:
([^\s])[^\s]*/
You could also just use:
[^\s]+/
And use the first character of the match (or perhaps you need the rest anyway).
If you want to be able to scan the whole document:
/(?<=(^|\s))\S(?=\S*\/)/g
https://regex101.com/r/rN08sP/1
s = `12/5
x23/4.5
234.5/2
534/5.6
- 49.55/6.5
234.5/7`;
console.log(s.match(/(?<=(^|\s))\S(?=\S*\/)/g));
But if you want to extract that character in a short string: (did you mean there is a space in front?)
It'd be /\s(\S)\S*\//
const arr = [
" 12/5",
" x23/4.5",
" 234.5/7",
" 2 - 012.3/4"
];
arr.forEach(s => {
let result = s.match(/\s(\S)\S*\//);
if (result)
console.log("For", s, "result: ", result[1])
});
But if "beginning of line" is ok... so no space is needed in front, then /(^|\s)(\S)\S*\//:
const arr = [
"12/5",
"x23/4.5",
"234.5/7",
"2 - 012.3/4"
];
arr.forEach(s => {
let result = s.match(/(^|\s)(\S)\S*\//);
if (result)
console.log("For", s, "result: ", result[2])
});
But actually, if you don't mean literally a space but just boundary in general:
const arr = [
"12/5",
"x23/4.5",
"234.5/7",
"2 - 012.3/4"
];
arr.forEach(s => {
let result = s.match(/\b(\S)\S*\//);
if (result)
console.log("For", s, "result: ", result[1])
});
I have 2 types of strings. One of them has only 1 space and the second one has 3 spaces.
V1: "100 s" => 1 space. Number followed by a letter. Number can be 1..n digits.
V2: "2 W 10 h" => 3 spaces. Each number is followed by a letter. Again numbers can be 2..n digits.
I need to get rid of the spaces following the numbers. So the end results should be this:
V1: "100 s" -> "100s"
V2: "2 W 10 h" -> "2W 10h"
For now, I use JavaScript split function. However I need regex to replace in a more efficient way. Could you help me with that? Thanks.
const getDelayValue = delayString => {
const splitted = delayString.split(/\s+/);
if (splitted) {
if (splitted.length === 2) {
return `${splitted[0]}${splitted[1]}`;
}
return `${splitted[0]}${splitted[1]} ${splitted[2]}${splitted[3]}`;
}
return delayString;
}
Just replace numbers space string with numbers string:
str = `
100 s
2 W 10 h
`
console.log(
str.replace(/(\d+)\s+([a-z]+)/gi, "$1$2")
)
See here for the meaning of $1 in the replacement.
You can use a regex to remove the spaces
const str1 = '100 s';
const str2 = '2 W 10 h';
function removeSpace(str) {
// as # Keith pointed out, you can also use :
// return str.replace(/(\d+) +/g, '$1');
// \d is a shortcut for [0-9]
return str.replace(/([0-9]+) +/g, '$1');
}
console.log(removeSpace(str1));
console.log(removeSpace(str2));
We are matching a number followed by a space. And then replace it by the number only. To create and test your Regexp, you can use the website https://regex101.com/
I want all the proper natural numbers from a given string,
var a = "#1234abc 12 34 5 67 sta5ck over # numbrs ."
numbers = a.match(/d+/gi)
in the above string I should only match the numbers 12, 34, 5, 67, not 1234 from the first word 5 etc..
so numbers should be equal to [12,34,5,67]
Use word boundaries,
> var a = "#1234abc 12 34 5 67 sta5ck over # numbrs ."
undefined
> numbers = a.match(/\b\d+\b/g)
[ '12', '34', '5', '67' ]
Explanation:
\b Word boundary which matches between a word charcter(\w) and a non-word charcter(\W).
\d+ One or more numbers.
\b Word boundary which matches between a word charcter and a non-word charcter.
OR
> var myString = '#1234abc 12 34 5 67 sta5ck over # numbrs .';
undefined
> var myRegEx = /(?:^| )(\d+)(?= |$)/g;
undefined
> function getMatches(string, regex, index) {
... index || (index = 1); // default to the first capturing group
... var matches = [];
... var match;
... while (match = regex.exec(string)) {
..... matches.push(match[index]);
..... }
... return matches;
... }
undefined
> var matches = getMatches(myString, myRegEx, 1);
undefined
> matches
[ '12', '34', '5', '67' ]
Code stolen from here.
If anyone is interested in a proper regex solution to match digits surrounded by space characters, it is simple for languages that support lookbehind (like Perl and Python, but not JavaScript at the time of writing):
(?<=^|\s)\d+(?=\s|$)
Debuggex PCRE Demo
As illustrated in the accepted answer, in languages that don't support lookbehind, it is necessary to use a hack, e.g. to include the 1st space in the match, while keepting the important stuff in a capturing group:
(?:^|\s)(\d+)(?=\s|$)
Debuggex JavaScript Demo
Then you just need to extract that capturing group from the matches, see e.g. this answer to How do you access the matched groups in a JavaScript regular expression?