Replace string using regular expression at specific position dynamically set - javascript

I want to use regular expression to replace a string from the matching pattern string.
Here is my string :
"this is just a simple text. this is just a simple text. this is just a simple text. this is just a simple text. How are you man today. I Have been working on this."
Now, I have a situation that, I want to replace "just a simple" with say "hello", but only in the third occurrence of a string. So can anyone guide me through this I will be very helpful. But the twist comes here. The above string is dynamic. The user can modify or change text.
So how can I check, if the user add "this is just a simple text" one or more times at the start or before the third occurrence of string which changes my string replacement position?
Sorry if I am unclear; But any guidance or help or any other methods will be helpful.

You can use this regex:
(?:.*?(just a simple)){3}
Working demo

You can use replace with a dynamically built regular expression and a callback in which you count the occurrences of the searched pattern :
var s = "this is just a simple text. this is just a simple text. this is just a simple text. this is just a simple text. How are you man today. I Have been working on this.",
pattern = "just a simple",
escapedPattern = pattern.replace(/[-\/\\^$*+?.()|[\]{}]/g, '\\$&'),
i=0;
s = s.replace(new RegExp(escapedPattern,'g'), function(t){ return ++i===3 ? "hello" : t });
Note that I used this related QA to escape any "special" characters in the pattern.

Try
$(selector)
.data("r", ["simple text", 3, "hello"])
.text(function (i, o) {
var r = $(this).data("r");
return o.replace(new RegExp(r[0], "g"), function (m) {
++i;
return (i === r[1]) ? r[2] : m
})
}).data("r", []);
jsfiddle http://jsfiddle.net/guest271314/2fm91qox/
See
Find and replace nth occurrence of [bracketed] expression in string
Replacing the nth instance of a regex match in Javascript
JavaScript: how can I replace only Nth match in the string?

Related

RegEx loop behaviour in TypeScript - Angular

I have strange problem with regex, im trying to check the user input in contentEditable div with regex, after each keydown, and if it match for example "hello" or "status", it should return modified text with <span style="color: purple">hello<span>. And it works properly with unique words, phrases or on paste, but when i declare both "hello" and "hello world" as key words, and type it in contentEditable, regex match only "hello", even if "hello world" is first in my array of strings.
Here is the code of my function:
searchByRegEx(wordsArr: string[], sentence: string): string {
let matchingWords = []; // matching words array
wordsArr.forEach((label) => {
const regEx = new RegExp(label, 'gi');
regEx.lastIndex = 0
let match = regEx.exec(sentence);
while (match) {
// console.log(match) - results of this console.log below
matchingWords.push(match[0]);
match = regEx.exec(sentence);
}
});
matchingWords = matchingWords.sort(function (a, b) {
return b.length - a.length;
});
matchingWords.forEach((word) => {
sentence = sentence.replaceAll(
word,
`<span style='color:${InputColorsHighlightValue.PURPLE}'>${word}</span>`
);
});
return sentence
}
}
And here is how i use it:
if (this.labels) {
textToShow = this.searchByRegEx(['hello', 'hello world'], textToShow)
}
This is how it looks in devTools, regex match properly, but ONLY on paste :
And here when i try to type it manually, it checks on every keydown, but cant match both hello and hello world. And as you can see, input in regex is the same as above:
I am struggling with this functionality and would appreciate any helpful advice.
Live version in stack blitz
There are a few things wrong with the actual regex in your example. If /hello?/gi is your input for a regex, consider the following things:
Your regex function already has those gi flags (new RegExp(label, 'gi');)
There are two ways to use a regex in javascript, new RegExp(regex) or /regex/. When you put a regex between slashes /hello/, you use the second one. Don't combine these two, it won't work!
You have a question mark on the single matchable part of your regex. This basically means that your regex does not have to match anything (and I don't know if your browser even knows how to process that correctly, I think the regex might be invalid). Since it should match either 'hello' or nothing at all, you should remove the ? parameter.
If you just want to match a plain string, not a pattern, don't use regexes. You can, but it's unnecessary obfuscation and probably computationally more demanding (i.e. lower performance).

Test if a sentence is matching a text declaration using regex

I want to test if a sentence like type var1,var2,var3 is matching a text declaration or not.
So, I used the following code :
var text = "int a1,a2,a3",
reg = /int ((([a-z_A-Z]+[0-9]*),)+)$/g;
if (reg.test(text)) console.log(true);
else console.log(false)
The problem is that this regular expression returns false on text that is supposed to be true.
Could someone help me find a good regular expression matching expressions as in the example above?
You have a couple of mistekes.
As you wrote, the last coma is required at the end of the line.
I suppose you also want to match int abc123 as correct string, so you need to include letter to other characters
Avoid using capturing groups for just testing strings.
const str = 'int a1,a2,a3';
const regex = /int (?:[a-zA-Z_](?:[a-zA-Z0-9_])*(?:\,|$))+/g
console.log(regex.test(str));
You will need to add ? after the comma ,.
This token ? matches between zero and one.
Notice that the last number in your text a3 does not have , afterward.
int ((([a-z_A-Z]+[0-9]*),?)+)$

Regular expression to match a string which is NOT matched by a given regexp

I've been hoving around by some answers here, and I can't find a solution to my problem:
I have this regexp which matches everyting inside an HTML span tag, including contents:
<span\b[^>]*>(.*?)</span>
and I want to find a way to make a search in all the text, except for what is matched with that regexp.
For example, if my text is:
var text = "...for there is a class of <span class="highlight">guinea</span> pigs which..."
... then the regexp would match:
<span class="highlight">guinea</span>
and I want to be able to make a regexp such that if I search for "class", regexp will match "...for there is a class of..."
and will not match inside the tag, like in
"... class="highlight"..."
The word to be matched ("class") might be anywhere within the text. I've tried
(?!<span\b[^>]*>(.*?)</span>)class
but it keeps searching inside tags as well.
I want to find a solution using only regexp, not dealing with DOM nor JQuery. Thanks in advance :).
Although I wouldn't recommend this, I would do something like below
(class)(?:(?=.*<span\b[^>]*>))|(?:(?<=<\/span>).*)(class)
You can see this in action here
Rubular Link for this regex
You can capture your matches from the groups and work with them as needed. If you can, use a HTML parser and then find matches from the text element.
It's not pretty, but if I get you right, this should do what you wan't. It's done with a single RegEx but js can't (to my knowledge) extract the result without joining the results in a loop.
The RegEx: /(?:<span\b[^>]*>.*?<\/span>)|(.)/g
Example js code:
var str = '...for there is a class of <span class="highlight">guinea</span> pigs which...',
pattern = /(?:<span\b[^>]*>.*?<\/span>)|(.)/g,
match,
res = '';
match = pattern.exec(str)
while( match != null )
{
res += match[1];
match = pattern.exec(str)
}
document.writeln('Result:' + res);
In English: Do a non capturing test against your tag-expression or capture any character. Do this globally to get the entire string. The result is a capture group for each character in your string, except the tag. As pointed out, this is ugly - can result in a serious number of capture groups - but gets the job done.
If you need to send it in and retrieve the result in one call, I'd have to agree with previous contributors - It can't be done!

Need a regex that finds "string" but not "[string]"

I'm trying to build a regular expression that parses a string and skips things in brackets.
Something like
string = "A bc defg hi [hi] jkl mnop.";
The .match() should return "hi" but not [hi]. I've spent 5 hours running through RE's but I'm throwing in the towel.
Also this is for javascript or jquery if that matters.
Any help is appreciated. Also I'm working on getting my questions formatted correctly : )
EDIT:
Ok I just had a eureka moment and figured out that the original RegExp I was using actually did work. But when I was replaces the matches with the [matches] it simply replaced the first match in the string... over and over. I thought this was my regex refusing to skip the brackets but after much time of trying almost all of the solutions below, I realized that I was derping Hardcore.
When .replace was working its magic it was on the first match, so I quite simply added a space to the end of the result word as follows:
var result = string.match(regex);
var modifiedResult = '[' + result[0].toString() + ']';
string.replace(result[0].toString() + ' ', modifiedResult + ' ');
This got it to stop targeting the original word in the string and stop adding a new set of brackets to it with every match. Thank you all for your help. I am going to give answer credit to the post that prodded me in the right direction.
preprocess the target string by removing everything between brackets before trying to match your RE
string = "A bc defg hi [hi] jkl mnop."
tmpstring = string.replace(/\[.*\]/, "")
then apply your RE to tmpstring
correction: made the match for brackets eager per nhahtd comment below, and also, made the RE global
string = "A bc defg hi [hi] jkl mnop."
tmpstring = string.replace(/\[.*?\]/g, "")
You don't necessarily need regex for this. Simply use string manipulation:
var arr = string.split("[");
var final = arr[0] + arr[1].split("]")[1];
If there are multiple bracketed expressions, use a loop:
while (string.indexOf("[") != -1){
var arr = string.split("[");
string = arr[0] + arr.slice(1).join("[").split("]").slice(1).join("]");
}
Using only Regular Expressions, you can use:
hi(?!])
as an example.
Look here about negative lookahead: http://www.regular-expressions.info/lookaround.html
Unfortunately, javascript does not support negative lookbehind.
I used http://regexpal.com/ to test, abcd[hi]jkhilmnop as test data, hi(?!]) as the regex to find. It matched 'hi' without matching '[hi]'. Basically it matched the 'hi' so long as there was not a following ']' character.
This of course, can be expanded if needed. This has a benefit of not requiring any pre-processing for the string.
r"\[(.*)\]"
Just play arounds with this if you wanto to use regular expressions.
What do yo uwant to do with it? If you want to selectively replace parts like "hi" except when it's "[hi]", then I often use a system where I match what I want to avoid first and then what I want to watch; if it matches what I want to avoid then I return the match, otherwise I return the processed match.
Like this:
return string.replace(/(\[\w+\])|(\w+)/g, function(all, m1, m2) {return m1 || m2.toUpperCase()});
which, with the given string, returns:
"A BC DEFG HI [hi] JKL MNOP."
Thus: it replaces every word with uppercase (m1 is empty), except if the word is between square brackets (m1 is not empty).
This builds an array of all the strings contained in [ ]:
var regex = /\[([^\]]*)\]/;
var string = "A bc defg hi [hi] [jkl] mnop.";
var results=[], result;
while(result = regex.exec(string))
results.push(result[1]);
edit
To answer to the question, this regex returns the string less all is in [ ], and trim whitespaces:
"A bc defg [hi] mnop [jkl].".replace(/(\s{0,1})\[[^\]]*\](\s{0,1})/g,'$1')
Instead of skipping the match you can probably try something different - match everything but do not capture the string within square brackets (inclusive) with something like this:
var r = /(?:\[.*?[^\[\]]\])|(.)/g;
var result;
var str = [];
while((result = r.exec(s)) !== null){
if(result[1] !== undefined){ //true if [string] matched but not captured
str.push(result[1]);
}
}
console.log(str.join(''));
The last line will print parts of the string which do not match the [string] pattern. For example, when called with the input "A [bc] [defg] hi [hi] j[kl]u m[no]p." the code prints "A hi ju mp." with whitespaces intact.
You can try different things with this code e.g. replacing etc.

Regular expressions for parsing "real" words in JavaScript

I've got some text where some words are "real" words, and others are masks that will be replaced with some text and that are surrounded with, say, "%". Here's the example:
Hello dear %Name%! You're %Age% y.o.
What regular expression should I use to get "real" words, without using lookbehind, because they don't exist in JavaScript?
UPD: I want to get words "Hello", "dear", "you're", "y.o.".
If I've understood your question correctly this might work.
I would go about it the other way around, instead of finding the real words I would remove the "fake-words."
s = "Hello dear %Name%! You're %Age% y.o."
realWords = s.replace(/%.*?%/g, "").split(/ +/)
You could use split to get the words and filter the words afterwards:
var str = "Hello dear %Name%! You're %Age% y.o.", words;
words = str.split(/\s+/).filter(function(val) {
return !/%[^%]*%/.test(val);
});
To do a search and replace with regexes, use the string's replace() method:
myString.replace(/replaceme/g, "replacement")
Using the /g modifier makes sure that all occurrences of "replaceme" are replaced. The second parameter is an normal string with the replacement text.
You can match the %Something% matches using %[^%]*?%, but how are you storing all of the individual mask values like Name and Age?
Use regular expression in Javascript and split the string based on matching regular expression.
//javascript
var s = "Hello dear %Name%! You're %Age% y.o.";
words = s.split(/%[^%]*?%/i);
//To get all the words
for (var i = 0; i < words.length; i++) {
}

Categories

Resources