How can you match text that appears between delimiters, but not match the delimiters themselves?
Text
DoNotFindMe('DoNotFindMe')
DoNotFindMe(FindMe)
DoNotFindMe(FindMe,FindMe)
DoNotFindMe(FindMe,FindMe,FindMe)
Script
text = text.replace(/[\(,]([a-zA-Z]*)[,\)]/g, function(item) {
return "'" + item + "'";
});
Expected Result
DoNotFindMe('DoNotFindMe')
DoNotFindMe('FindMe')
DoNotFindMe('FindMe','FindMe')
DoNotFindMe('FindMe','FindMe','FindMe')
https://regex101.com/r/tB1nE2/1
Here's a pretty simple way to do it:
([a-zA-Z]+)(?=,|\))
This looks for any word that is succeeded by either a comma or a close-parenthesis.
var s = "DoNotFindMe('DoNotFindMe')\nDoNotFindMe(FindMe)\nDoNotFindMe(FindMe,FindMe)\nDoNotFindMe(FindMe,FindMe,FindMe)";
var r = s.replace(/([a-zA-Z]+)(?=,|\))/g, "'$1'" );
alert(r);
Used the same test code as the other two answers; thanks!
You can use:
var s = "DoNotFindMe('DoNotFindMe')\nDoNotFindMe(FindMe)\nDoNotFindMe(FindMe,FindMe)\nDoNotFindMe(FindMe,FindMe,FindMe)";
var r = s.replace(/(\([^)]+\))/g, function($0, $1) {
return $1.replace(/(\b[a-z]+(?=[,)]))/gi, "'$1'"); }, s);
DoNotFindMe('DoNotFindMe')
DoNotFindMe('FindMe')
DoNotFindMe('FindMe','FindMe')
DoNotFindMe('FindMe','FindMe','FindMe')
Here's a solution that avoids the function argument. It's a bit wonky, but works. Basically, you explicitly match the left delimiter and include it in the replacement string via backreference so it won't get dropped, but then you have to use a positive look-ahead assertion for the right delimiter, because otherwise the match pointer would be moved ahead of the right delimiter for the next match, and so it then wouldn't be able to match that delimiter as the left delimiter of the following delimited word:
var s = "DoNotFindMe('DoNotFindMe')\nDoNotFindMe(FindMe)\nDoNotFindMe(FindMe,FindMe)\nDoNotFindMe(FindMe,FindMe,FindMe)";
var r = s.replace(/([,(])([a-zA-Z]*)(?=[,)])/g, "$1'$2'" );
alert(r);
results in
DoNotFindMe('DoNotFindMe')
DoNotFindMe('FindMe')
DoNotFindMe('FindMe','FindMe')
DoNotFindMe('FindMe','FindMe','FindMe')
(Thanks anubhava, I stole your code template, cause it was perfect for my testing! I gave you an upvote for it.)
Related
I am using Javascript and currently looking for a way to match as many of my pattern's letters as possible, maintaining the original order..
For example a search pattern queued should return the march Queue/queue against the any of the following search strings:
queueTable
scheduledQueueTable
qScheduledQueueTable
As of now I've reached as far as this:
var myregex = new RegExp("([queued])", "i");
var result = myregex.exec('queueTable');
but it doesn't seem to work correctly as it highlights the single characters q,u,e,u,e and e at the end of the word Table.
Any ideas?
Generate the regex with optional non-capturing group part where regex pattern can be generate using Array#reduceRight method.
var myregex = new RegExp("queued"
.split('')
.reduceRight(function(str, s) {
return '(?:' + s + str + ')?';
}, ''), "i");
var result = myregex.exec('queueTable');
console.log(result)
The method generates regex : /(?:q(?:u(?:e(?:u(?:e(?:d?)?)?)?)?)?)?/
UPDATE : If you want to get the first longest match then use g modifier in regex and find out the largest using Array#reduce method.
var myregex = new RegExp(
"queued".split('')
.reduceRight(function(str, s) {
return '(?:' + s + str + ')?';
}, ''), "ig");
var result = 'qscheduledQueueTable'
.match(myregex)
.reduce(function(a, b) {
return a.length > b.length ? a : b;
});
console.log(result);
I think the logic would have to be something like:
Match as many of these letters as possible, in this order.
The only real answer that comes to mind is to get the match to continue if possible, but allow it to bail out. In this case...
myregex = /q(?:u(?:e(?:u(?:e(?:d|)|)|)|)|)/;
You can generate this, of course:
function matchAsMuchAsPossible(word) { // name me something sensible please!
return new RegExp(
word.split("").join("(?:")
+ (new Array(word.length).join("|)"))
);
}
You are using square brackets - which mean that it will match a single instance of any character listed inside.
There are a few ways of interpreting your intentions:
You want to match the word queue with an optional 'd' at the end:
var myregex = new RegExp("queued?", "i");
var result = myregex.exec('queueTable');
Note this can be shorter try this:
'queueTable'.match(/queued?/i);
I also removed the brackets as these were not adding anything here.
This link provides some good examples that may help you further: https://www.w3schools.com/js/js_regexp.asp
When you use [] in a regular expression, it means you want to match any of the characters inside the brackets.
Example: if I use [abc] it means "match a single character, and this character can be 'a', 'b' or 'c'"
So in your code [queued] means "match a single character, and this character can be 'q', 'u', 'e' or 'd'" - note that 'u' and 'e' appear twice so they are redundant in this case. That's why this expression matches just one single character.
If you want to match the whole string "queued", just remove the brackets. But in this case it won't match, because queueTable doesn't have 'd'. If you want 'd' to be optional, you can use queued? as already explained in previous answers.
Try something like the following :
var myregex = /queued?\B/g;
var result = myregex.exec('queueTable');
console.log(result);
I have regexp that extracts values between parentheses.
It's working most of the time but not when it ends with a parentheses
var val = 'STR("ABC(t)")';
var regExp = /\(([^)]+)\)/;.
var matches = regExp.exec(val);
console.log(matches[1]); //"ABC(t"
What I want is "ABC(t)".
Any ideas how I can modify my regexp to Achive this?
Update
The value is always inside the parentheses.
Some examples:
'ASD("123")'; => '123'
'ASD(123)'; => '123'
'ASD(aa(10)asda(459))'; => 'aa(10)asda(459)'
So first there is some text (always text). Then there is a (, and it always ends with a ). I want the value between.
You may use greedy dot matching inside Group 1 pattern: /\((.+)\)/. It will match the first (, then any 1+ chars other than linebreak symbols and then the last ) in the line.
var vals = ['STR("ABC(t)")', 'ASD("123")', 'ASD(123)', 'ASD(aa(10)asda(459))'];
var regExp = /\((.+)\)/;
for (var val of vals) {
var matches = regExp.exec(val);
console.log(val, "=>", matches[1]);
}
Answering the comment: If the texts to extract must be inside nested balanced parentheses, either a small parsing code, or XRegExp#matchRecursive can help. Since there are lots of parsing codes around on SO, I will provide XRegExp example:
var str = 'some text (num(10a ) ss) STR("ABC(t)")';
var res = XRegExp.matchRecursive(str, '\\(', '\\)', 'g');
console.log(res);
<script src="https://cdnjs.cloudflare.com/ajax/libs/xregexp/2.0.0/xregexp-all-min.js"></script>
I use
str.replace(/(^,)|(,$)/g, '')
to remove leading and trailing commas.
How can I extend it so I also remove two consecutive commas?
So ,some text,,more text, should become some text,more text?
One way would be to chain with
str.replace(/(^,)|(,$)/g, '').replace(/,,/g, ',')
but then ,some text,,,,more text, will become some text,,more text instead of some text,more text.
Since you appear to be using the str as a source for an array, you can replace all the .replace calls with:
var str = ",some text,,,,more text,";
var resultArray = str.split(',') // Just split the string.
.filter(function(item){ // Then filter out empty items
return item !== '';
});
console.log(resultArray)
No need to worry about leading, trailing or double comma's.
Remove the leading and trailing commas, and then replace multiple consecutive commas by single comma
str.replace(/^,|,$|(,)+/g, '$1');
,+ will match one or more comma, g-global flag to replace all occurrences of it.
var str = ',some text,,more text,';
str = str.replace(/^,|,$|(,)+/g, '$1');
console.log(str);
You may add an alternative branch and enclose it with a capturing group and then use a replace callback method where you can analyze the match groups and perform the replacement accordingly:
var s = ',some text,,,,more text,';
var res = s.replace(/^,|,$|(,+)/g, function(m,g1) {
return g1 ? ',' : '';
});
console.log(res);
To split with commas and get no empty entries in the resulting array, use a simple
console.log(',some text,,,,more text,'.split(',').filter(Boolean));
You could add a positive lookahead with another comma.
var str = ',some text,,more text,';
str = str.replace(/^,|,$|,(?=,)/g, '')
console.log(str);
What about one replace only like: ",some text,,,,more text,".replace(/(^,)|(,$)|,(?=,)/g, '');
[EDIT]
Note that lookbehinds don't work in javascript. so you can only use a lookahead like so.
I'm working on a regex that must match only the text inside quotes but not in a comment, my macthes must only the strings in bold
<"love";>
>/*"love"*/<
<>'love'<>
"lo
more love
ve"
I'm stunck on this:
/(?:((\"|\')(.|\n)*?(\"|\')))(?=(?:\/\**\*\/))/gm
The first one (?:((\"|\')(.|\n)*?(\"|\'))) match all the strings
the second one (?=(?:\/\**\*\/)) doesn't match text inside quotes inside /* "mystring" */
bit my logic is cleary wrong
Any suggestion?
Thanks
Maybe you just need to use a negative lookahead to check for the comment end */?
But first, I'd split the string into separate lines
var arrayOfLines = input_str.split(/\r?\n/);
or, without empty lines:
var arrayOfLines = input_str.match(/[^\r\n]+/g);
and then use this regex:
["']([^'"]+)["'](?!.*\*\/)
Sample code:
var rebuilt_string = ''
var re = /["']([^'"]+)["'](?!.*\*\/)/g;
var subst = '<b>$1</b>';
for (i = 0; i < arrayOfLines.length; i++)
{
rebuilt_string = rebuilt_string + arrayOfLines[i].replace(re, subst) + "\r\n";
}
The way to avoid commented parts is to match them before. The global pattern looks like this:
/(capture parts to avoid)|target/
Then use a callback function for the replacement (when the capture group exists, return the match without change, otherwise, replace the match with what you want.
Example:
var result = text.replace(/(\/\*[^*]*(?:\*+(?!\/)[^*]*)*\*\/)|"[^"\\]*(?:\\[\s\S][^"\\]*)*"|'[^'\\]*(?:\\[\s\S][^'\\]*)*'/g,
function (m, g1) {
if (g1) return g1;
return '<b>' + m + '</b>';
});
I have a problem. I have a string - "\,str\,i,ing" and i need to split by comma before which not have slash. For my string - ["\,str\,i", "ing"]. I'm use next regex
myString.split("[^\],", 2)
but it's doesn't worked.
Well, this is ridiculous to avoid the lack of lookbehind but seems to get the correct result.
"\\,str\\,i,ing".split('').reverse().join('').split(/,(?=[^\\])/).map(function(a){
return a.split('').reverse().join('');
}).reverse();
//=> ["\,str\,i", "ing"]
Not sure about your expected output but you are specifying string not a regex, use:
var arr = "\,str\,i,ing".split(/[^\\],/, 2);
console.log(arr);
To split using regex, wrap your regex in /..../
This is not easily possible with js, because it does not support lookbehind. Even if you'd use a real regex, it would eat the last character:
> "xyz\\,xyz,xyz".split(/[^\\],/, 2)
["xyz\\,xy", "xyz"]
If you don't want the z to be eaten, I'd suggest:
var str = "....";
return str.split(",").reduce(function(res, part) {
var l = res.length;
if (l && res[l-1].substr(-1) == "\\" || l<2)
// ^ ^^ ^
// not the first was escaped limit
res[l-1] += ","+part;
else
res.push(part);
return;
}, []);
Reading between the lines, it looks like you want to split a string by , characters that are not preceded by \ characters.
It would be really great if JavaScript had a regular expression lookbehind (and negative lookbehind) pattern, but unfortunately it does not. What it does have is a lookahead ((?=) )and negative lookahead ((?!)) pattern. Make sure to review the documentation.
You can use these as a lookbehind if you reverse the string:
var str,
reverseStr,
arr,
reverseArr;
//don't forget to escape your backslashes
str = '\\,str\\,i,ing';
//reverse your string
reverseStr = str.split('').reverse().join('');
//split the array on `,`s that aren't followed by `\`
reverseArr = reverseStr.split(/,(?!\\)/);
//reverse the reversed array, and reverse each string in the array
arr = reverseArr.reverse().map(function (val) {
return val.split('').reverse().join('');
});
You picked a tough character to match- a forward slash preceding a comma is apt to disappear while you pass it around in a string, since '\,'==','...
var s= 'My dog, the one with two \\, blue \\,eyes, is asleep.';
var a= [], M, rx=/(\\?),/g;
while((M= rx.exec(s))!= null){
if(M[1]) continue;
a.push(s.substring(0, rx.lastIndex-1));
s= s.substring(rx.lastIndex);
rx.lastIndex= 0;
};
a.push(s);
/* returned value: (Array)
My dog
the one with two \, blue \,eyes
is asleep.
*/
Find something which will not be present in your original string, say "###". Replace "\\," with it. Split the resulting string by ",". Replace "###" back with "\\,".
Something like this:
<script type="text/javascript">
var s1 = "\\,str\\,i,ing";
var s2 = s1.replace(/\\,/g,"###");
console.log(s2);
var s3 = s2.split(",");
for (var i=0;i<s3.length;i++)
{
s3[i] = s3[i].replace(/###/g,"\\,");
}
console.log(s3);
</script>
See JSFiddle