RegExp Weirdness in JavaScript - javascript

I have a variable string in my JavaScript code containing a comma delimited list of words and or phrases, for example:
String 1 : “abc, def hij, klm”
String 2 : “abc, def”
I want to insert the word ‘and’ after the last comma in the string to get
String 1 : “abc, def hij, and klm”
String 2 : “abc, and def”
I put together the following code:
// replace the last comma in the list with ", and"
var regEx1 = new RegExp(",(?=[A-z ]*$)" )
var commaDelimList = commaDelimList.replace(regEx1, ", and ");
The problem is that it does not work if the comma delimited string has only two items separated by one comma.
So the results of the above example are
String 1 : ”abc, def hij, and klm”
String 2 : “abc, def”
Why is the RegExp not working and what can I use to get the result I want?

Not sure a regex was the right way to go there...
Why not use LastIndexOf and replace that with your string?

Since this is a relatively straight forward task, a little string manipulation may be beneficial - you'll realize better performance too.
var str = 'abc, def, hij, klm',
index = str.lastIndexOf(','),
JOINER = ', and';
//'abc, def, hij, and klm'
str.slice(0, index) + JOINER + str.slice(index+1);

Haven't tried you one but this works
'abc, def'.replace( /,(?=[A-z ]*$)/, ", and" )

Related

Matching user entered input with regex and trimming the invalid inputs to match regex

I have a regex : /^PVER : [a-z|A-Z|0-9|_]* [/] [a-z|A-Z|0-9|_]* ; 0$/
let's consider for example that "PVER : abc / def ; 0" is a valid input.
If the entered input is : " PVER : abc //// def ; 0"
How do I convert this input to make it valid like in the first example?
Use this regex to find multiple consecutive occurrences of / and replace it with just one /
const res = " PVER : abc //// def ; 0".replace(/(\/)\1+/g, "/");
console.log(res);
Or you could modify your original regex to also match multiple consecutive occurrences of /
const res = "PVER : abc //// def ; 0".match(/^PVER : [a-z|A-Z|0-9|_]* [/]+ [a-z|A-Z|0-9|_]* ; 0$/g);
console.log(res);
To turn the second string into the first string, you could replace multiple 2 or more whitespace characters or forward slashes by a single one. Then trim the string to remove the leading space.
let str = " PVER : abc //// def ; 0";
let res = str.trim()
.replace(/\s{2,}/g, ' ')
.replace(/\/{2,}/, '/');
console.log(res);
Instead of changing the input, you might update the regex. This pattern [a-z|A-Z|0-9|_] is a character class which will match one of the many listed. If you don't want to match a pipe |, you could write it as \w.
In your second example you have to match one or more times a space (or tab perhaps) for which you might use [ \t], or use \s to match a whitespace character and one or more times a forward slash to get match.
Using quantifiers, you could update your regex to:
^\s*PVER\s*:\s*\w+\s+\/+\s*\w+\s+;\s+0$
Regex demo
[
"PVER : abc / def ; 0",
" PVER : abc //// def ; 0",
"test"
].forEach(s => {
console.log(s + " =>> " + /^\s*PVER\s*:\s*\w+\s+\/+\s*\w+\s+;\s+0$/.test(s));
});

Split a string of strings by 2 delimeters

My string looks like
"<!number|Foo bar> <!number|Foo bar> <!number|foo bar>"
I have like to split the string by "<" and ">" so that the new array becomes
["<!number|string>", "<!number|string>" ].
I tried str.split('> <'), which gives me
["<!numer|string", "!number|string>"].
Also I tried using regex to str.split(/\<> /)
which gives me ["<!number|string> <!number|string>"].
How to split it correctly?
At work so I can't fix the nitty gritty with the regex, but the below works given the string
const str = `<!1|Foo bar> <!2|Bar Baz> <!3| xxx yyy>`;
console.log(str.split(/(<[\s\S]*?>)/gm).filter((n)=> { return (n!="" && n!=" ") }));
Just split on space:
let str = "<!number|string> <!number|string> <!number|string>";
console.log(str.split(" "));

Extraction of string using regex in javascript

I have a string of the following format:
"hello(%npm%)hi"
My goal is to split the string into three parts
a) hello
b) (%npm%)
c) hi
I am using regex as follows:
var myString = "hello(%npm%)hi".match(/[a-z]*/);
var backdtring = "hello(%npm%)hi".match(/\)[a-z]*/);
var midstring = "hello(%npm%)hi".match(/\(\%[a-z]*\%\)/);
var res = backdtring.replace(")", "");
https://jsfiddle.net/1988/ff6aupmL/
I am trying in jsfiddle , where theres an error in the line:
var res = backdtring.replace(")", "");
"backdtring.replace is not a function" .
Whats wrong in the replace function above?
Update:
Also, have I used the best practices of regular expressions ?
As it has been mentioned in the comments, you are trying to use a String#replace method on an array, see the description of the return value of String#match:
An Array containing the entire match result and any parentheses-captured matched results; null if there were no matches.
To streamline tokenization, I'd rather use .split(/(\([^()]*\))/) to get all substrings in parentheses and the substrings that remain:
var s = "hello(%npm%)hi";
var res = s.split(/(\([^()]*\))/);
console.log(res);
Details:
(\([^()]*\)) - the pattern is enclosed with capturing group so as split could return both the substrings that match and those that do not match the pattern
\( -a literal (
[^()]* - 0+ chars other than ( and )
\) - a literal ).

split string based on a symbol

I'm trying to split a string into an array based on the second occurrence of the symbol _
var string = "this_is_my_string";
I want to split the string after the second underscore. The string is not always the same but it always has 2 or more underscores in it. I always need it split on the second underscore.
In the example string above I would need it to be split like this.
var split = [this_is, _my_string];
var string = "this_is_my_string";
var firstUnderscore = string.indexOf('_');
var secondUnderscore = string.indexOf('_', firstUnderscore + 1);
var split = [string.substring(0, secondUnderscore),
string.substring(secondUnderscore)];
Paste it into your browser's console to try it out. No need for a jsFiddle.
var string = "this_is_my_string";
var splitChar = string.indexOf('_', string.indexOf('_') + 1);
var result = [string.substring(0, splitChar),
string.substring(splitChar, string.length)];
This should work.
var str = "this_is_my_string";
var matches = str.match(/(.*?_.*?)(_.*)/); // MAGIC HAPPENS HERE
var firstPart = matches[1]; // this_is
var secondPart = matches[2]; // _my_string
This uses regular expressions to find the first two underscores, and captures the part up to it and the part after it. The first subexpression, (.*?_.*?), says "any number of characters, an underscore, and again any number of characters, keeping the number of characters matched as small as possible, and capture it". The second one, (_.*) means "match an underscore, then any number of characters, as much of them as possible, and capture it". The result of the match function is an array starting with the full matched region, followed by the two captured groups.
I know this post is quite old... but couldn't help but notice that no one provided a working solution. Here's one that works:
String str = "this_is_my_string";
String undScore1 = str.split("_")[0];
String undScore2 = str.split("_")[1];
String bothUndScores = undScore1 + "_" + undScore2 + "_";
String allElse = str.split(bothUndScores)[1];
System.out.println(allElse);
This is assuming you know there will always be at least 2 underscores - "allElse" returns everything after the second occurrence.

Use RegExp to match a parenthetical number then increment it

I've been trying to find a way to match a number in a Javascript string that is surrounded by parenthesis at the end of the string, then increment it.
Say I have a string:
var name = "Item Name (4)";
I need a RegExp to match the (4) part, and then I need to increment the 4 then put it back into the string.
This is the regex I have so far:
\b([0-9]+)$\b
This regex does not work. Furthermore, I do not know how to extract the integer retrieved and put it back in the same location in the string.
Thanks.
The replace method can take a function as its second argument. It gets the match (including submatches) and returns the replacement string. Others have already mentioned that the parentheses need to be escaped.
"Item Name (4)".replace(/\((\d+)\)/, function(fullMatch, n) {
return "(" + (Number(n) + 1) + ")";
});
I can can only think of a way of doing it in three steps: Extract, increment and replace.
// Tested on rhino
var name = "Item Name (4)";
var re = /\((\d+)\)/;
match = re.exec(name);
number = parseInt(match[1]) + 1;
name = name.replace(re, "(" + number + ")");
The important parts of the pattern:
You need to escape the parens to match literal parens
You also need the to use parens to capture the number so that you can extract it from the match.
\d matches a digit and is shorter and more common than writing out [0-9].
In order this pattern to work you shoud escape parenthesis. In addition \b and $ are unneeded. Thus
var s = "Item Name (4)";
var match = /\((\d+)\)/.exec( s );
var n = Number(match[1])+1;
alert( s.replace( /\(\d+\)/, '('+n+')' ) );
Solution by david.clarke (tested)
"Item Name (4)".replace(/\(([0-9]+)\)/, '('+(1+RegExp.$1) + ')');
But I think it is too concise
UPD: It turned out that RegExp.$1 can't be used as part of replace parameter, because it works only in Opera
'var name = "Item Name (4)"'.replace(/\(([\d]+)\)/, 1 + $1);
(untested)

Categories