I am developing context menu add-on for Firefox. I am trying to get the selectedText and validate if it is a number. If it is a number i am using that number value to process further.
But, i got stuck at a point where i am trying to replace [(,)] using regex in javascript replace method.
Following is the code which fails to map any number starting/ending with ( or ):
var menuItemLRG = contextMenu.Item({
label: "LRG",
data: "http://myurl/&val=:",
contentScript: 'self.on("click", function (node, data) {' +
' var selectedText = window.getSelection().toString();' +
' var formattedText1 = selectedText.trim();' +
' var formattedText2 = formattedText1.replace(/^[,\[\]()]*/g,"");' +
' var formattedText3 = formattedText2.replace(/[,\[\]()]*$/g,"");' +
' console.log(formattedText3); '+
' var regExp = new RegExp(/^[0-9]+$/);' +
' if (regExp.test(formattedText3) == true) {' +
' console.log("URL to follow :"+data+formattedText3);' +
' window.open(data+formattedText3);' +
' } '+
'});'
});
Above code fails to replace ( or ) in sample inputs: (5663812, 11620033).
But, a vanilla test like the following succeeds:
<script>
var str = "(2342423,])";
var tmpVal1 = str.replace(/^[,\[\]()]*/g,"");
var tmpVal2 = tmpVal1.replace(/[,\[\]()]*$/g,"");
var regExp = new RegExp(/^[0-9]+$/);
if (regExp.test(tmpVal2) == true) {
alert(tmpVal2);
}
</script>
After many trial and error found the issue. When we try to escape a character inside a single quotes we need to add one more escape for the escape character to get recognized, otherwise the single escape \] will be considered as ] which leads to abrupt ending of of the regex pattern.
In this case:
' var formattedText2 = formattedText1.replace(/^[,\[\]()]*/g,"");'
is decoded as :
var formattedText2 = formattedText1.replace(/^[,[]()]*/g,"");
instead of as:
var formattedText2 = formattedText1.replace(/^[,\[\]()]*/g,"");
So, by adding one more escape character for an escape character resolved the pattern correctly:
' var formattedText2 = formattedText1.replace(/^[,\\[\\]()]*/g,"");'
Sorry for wasting your time in analyzing the cause, if any.
Related
I am new to node.js. I was practising a program to find a pattern in a string and extracting that part of line from the file.
File as:
Something written in a file saved as filename.ext.
At a line, it contains a link.
import "https:\//www.hostname.com/$path"
I want to extract the link from any line in a file.
I was trying to match the pattern to get index no of 'h' in 'http' and extracting it further. Stuck at nm() as it isn't working on variable as parameter.
var url=require('url')
var fs = require('fs');
var find = require('find');
var findInFiles = require('find-in-files');
var LineReader = require('linereader');
var nm = require('nanomatch');
var sol=require('./../bin/sol-merger')
var dir = './merged/';
var pth=process.cwd()+'/'+dir+'newfile.sol'
var flag=0
if (!fs.existsSync(dir)){
fs.mkdirSync(dir);
}
fs.createReadStream(sol.abs_path).pipe(fs.createWriteStream(dir+'/newfile.sol'));
findInFiles.find({'term': "http", 'flags': 'ig'}, 'merged/', '.sol$').then(function(results) {
//console.log("here...")
for (var result in results) {
var res = results[result];
console.log('found "' + res.matches[0] + '" ' + res.count+ ' times in "' + result + '"')
console.log(sol.fl+" "+result)
}
var lr=new LineReader(pth)
lr.on('error', function (err) {
console.log(err);
console.log("error")
lr.close();
});
lr.on('line', function (lineno, line) {
console.log(lineno + " " + line);
if(nm.contains(`$line`,'*"http**"*')){
console.log("found")
}
});
})
Change
findInFiles.find({'term': "http", 'flags': 'ig'}, 'merged/', '.sol$')
to
var regex = 'http.*?(?=\")'
findInFiles.find({term: regex, flags: 'g'}, 'merged/', '.sol$')
The regex matches http/https link till " is found at end of link, but doesn't capture " in group. (?=\") is positive lookahead match.
See regular expression's explanation and working example here - https://regex101.com/r/4RAr0Z/1
I would use regex, e.g.:
//read in eg with fs module
var _test = 'import "https://www.github.com/xyz/abc.txt" \n import "https://www.github.com/xyz/xab.txt"';
var _reg = /["](.*?)["]/gm;
var _my_matches = _test.match(_reg);
console.log(_my_matches); //array with all matches
Please note, this is a minimal example. I recommend to test out your required regex setup at https://regex101.com/ (or something similar)
This is my console.log:
str : +0-D : replace : Da href="Javascript:PostRating('','|P|622','+0')">+0</a>-D
I have the following function:
function replaceAll_withMatching(str, find, rep, prodId) {
//console.log(str + " : " + find + " : " + rep + " : " + prodId);
var returnString = "";
if (find.toLowerCase() == str.toLowerCase()) {
returnString = rep;
} else {
escfind = "\\" + find ;
var regexp = new RegExp(escfind, "i");
var match = regexp.test(str);
if (match) {
var regAHREF = new RegExp("\\<a", "i");
var AHREFMatch = regAHREF.test(str);
if (AHREFMatch == false) {
str = str.replace(regexp, rep);
str = replaceProductAll(str, PRODUCT_PLACEHOLD, prodId);
} else {
var aTagText = $($.parseHTML(str)).filter('a').text();
if ((find !== aTagText) && (aTagText.indexOf(find) < 0)) {
console.log(regexp);
console.log("str : " + str + " : replace : " + str.replace(regexp, rep));
str = str.replace(regexp, rep);
}
}
}
//console.log(str);
returnString = str;
}
//returnString = replaceProductAll(returnString, PRODUCT_PLACEHOLD, prodId);
return returnString;
}
This function looks for a "<a>" tag, if it doesn't find one then it does the replace. If it does find one it has some conditions that if everything checks out it does another replace.
The string that I'm passing in has been already "parsed" on the +0:
+0-D
In the second pass I'm expecting it to find the "D" in the above string, and then do the following replacement:
D
But as you can see, after the 2nd replace it is jumbling the string and producing malformed HTML
Da href="Javascript:PostRating('','|P|622','+0')">+0</a>-D
More Context:
I have a string that needs to have a replace done on it. This is existing code so I'm not in a position to rework the function.
The original string is: +0-D
This string gets passed into the function below multiple times looking for matches and then if it finds a match it will replace it with the value (also passed in as a parameter).
When the +0-D gets passed in the first time the +0 is matched and a replace is done: +0
Then the next time the string is passed in: +0-D. The function finds the D as a match and it looks like it attempts to do a replace. But it is on this pass that the string gets jumbled.
Ultimately what I'm expecting is this:
+0-D
This is what I'm currently getting after the 2nd attempt:
Da href="Javascript:PostRating('','|P|622','+0')">+0</a>-D
Further Context:
The +0-D is one of many strings this function handles. Some are very simple (i.e. Just +0), others are much more complex.
Question:
Based on the above, what do I need to do to get the regex to not jumble the string?
The problem was in the escfind:
escfind = "\\" + find;
var regexp = new RegExp(escfind,"i");
var match = regexp.test(str);
The first thing I did was in the 2nd replace clause I created a new RegExp to not use the "\\" + find;
if((find !== aTagText) && (aTagText.indexOf(find) < 0)){
try{
var regexp2 = new RegExp(find,"i");
var match2 = regexp2.test(str);
console.log(str.replace(regexp2,rep));
}catch(err){
console.log(err);
}
}
Then my string began to return as expected, however, when I opened it up to all the variations I was getting the Unexpected quantifier error.
Then I found this question - which lead me to escape out my find:
Once I replaced my code with this:
escfind = find.replace(/([*+.?|\\\[\]{}()])/g, '\\$1');
Then I got the output as expected:
<a href='+0'>+0</a>-<a href='D'>D</a>
I swear i tried figuring this out myself all day, but my regex-foo is just not that good.
I'm trying to create a small parser function to convert strings with urls to html coded and tags
I know how complex a regex can be trying to figure out which urls to covert to what from a big string, so what I did is simply prefix the string to covert with a flag to tell the parser how to format it, and post fix it with the ";" char to tell the parser where that particular URL ends. This way the parser has lesser guest work to do resulting in easier to regex-match and faster for execution. I really dont need a generalize match and replace all.
So my formatting is as follows, where "X" is the url string:
For URLs it will be url=X;
For IMAGES it will be img=X;
so anything in between my prefix and post fix must be converted accordingly..
So for example, for images in my document, the string could be:
click this image img=http://example.com/image1.jpg;
and i need that converted to
click this image <a href="http://example.com/image1.jpg" target="_blank">
<img class="img img-responsive" src="http://example.com/image1.jpg"/></a>
I am able to do this easily in PHP buy preg_match() function
preg_match('/\img=(.+?)\;/i', $item_des, $matches)
here's the code block:
I decided to push this routine to the browser instead of the backend (PHP) so i need similar or better JS solution.
Hoping anyone can help here, thanks!
try code below:
var str = "click this image img=http://example.com/image1.jpg;image2 img=http://example.com/image2.jpg;"
var phrases = str.split(';');
var totalRes = '';
phrases.forEach(function(str){
totalRes += processPhrase(str);
});
console.log(totalRes);
function processPhrase(str) {
var img = str.split('img=')
var res = '';
if (img.length > 1) { //img=X
var url = img[1].replace(';', '');
res = img[0] + "<a href='" + url + "' target='_blank'><img src='" + url + "'/></a>";
} else {
var url = str.split('url=');
//Do for url=X here
}
console.info(res);
return res;
}
You can use this regexp /(img|url)=(.+?);/g:
(img|url) : the type, should be grouped so we will know what to do with the value
= : literal "="
(.+?) : a number of characters (use the non-greedy ? so it will match as fewer as possible)
; : literal ";"
Read more about non-greedy regexps here.
Example:
var str = "click this image img=http://i.imgur.com/3wY30O4.jpg?a=123&b=456; and check this URL url=http://google.com/;. Bye!";
// executer is an object that has functions that apply the changes for each type (you can modify the functions for your need)
var executer = {
"url": function(e) {
return '<a target="_blank" href="' + e + '">' + e + '</a>';
},
"img": function(e) {
return '<a target="_blank" href="' + e + '"><img src="' + e + '"/></a>';
}
}
var res = str.replace(/(img|url)=(.+?);/g, function(m, type, value) {
return executer[type](value); // executer[type] will be either executer.url or executer.img, then we pass the value to that function and return its returned value
});
console.log(res);
I have the following string in a variable named js:
some code here
/* start-rotateControlOptions */
some more code here
on multiple
lines
/* end-rotateControlOptions */
some code here
And I want to end up with:
some code here
some code here
Basically escape everything between these 2 specific comments.
The following works:
js = js.replace(/\/\* start-rotateControlOptions \*\/([\s\S]*)\/\* end-rotateControlOptions \*\//, '');
But now I need to have the rotateControlOptions as a variable.
This is what I have tried to no avail:
js = escapeCode(js, 'rotateControlOptions');
function escapeCode(js, identifier) {
var re = new RegExp("/\/\* start-" + identifier + " \*\/([\s\S]*)\/\* end-" + identifier + " \*\//");
js = js.replace(re, '');
return js;
}
What am I doing wrong? I get no error.
Escape all the backslahes one more time and you don't need to add the forward slash delimiter inside the RegExp constructor.
var re = new RegExp("/\\* start-" + identifier + " \\*/([\\s\\S]*)/\\* end-" + identifier + " \\*/");
Example:
> var str = 'some code here\n/* start-rotateControlOptions */\nsome more code here\non multiple\nlines\n/* end-rotateControlOptions */\nsome code here';
> var re = new RegExp("/\\* start-" + identifier + " \\*/([\\s\\S]*)/\\* end-" + identifier + " \\*/\\n");
undefined
> console.log(str.replace(re, ''))
some code here
some code here
I want to replace a markdown image pattern with the given filename in the textarea with an empty string.
So the pattern is ![alt](http://somehost/uploads/filename.jpg)
This is the code I have now:
var content = target.val();
var fileName = someDynamicValue;
var regex = new RegExp(RegExp.escape('![') + '.*' + RegExp.escape(']') + RegExp.escape('(') + '.*' + RegExp.escape(fileName) + RegExp.escape(')'), 'i');
var found = regex.exec(content);
var newContent = content.replace(regex, "");
target.val(newContent);
RegExp.escape= function(s) {
return s.replace(/[-\/\\^$*+?.()|[\]{}]/g, '\\$&')
};
For example var fileName = filename.jpg. Then I need to match ![alt](http://somehost/uploads/filename.jpg) and replace it with an empty string.
Everything works great if the content includes one image. But if there are more then one, for example:
Some text ![alt](http://somehost/uploads/filename.jpg) some text ![alt2](http://somehost/uploads/filename2.jpg) more text.
then var found includes ![alt](http://somehost/uploads/filename.jpg)![alt2](http://somehost/uploads/filename2.jpg), but I need to match only ![alt](http://somehost/uploads/filename.jpg).
What regex I need in this case?
Use non-greedy quantifiers will do:
!\[(.*?)\]\((.*?)\)
You can check it out online: https://regex101.com/r/kfi8qI
Not sure how you are trying to put the strings together but
'.*' is greedily matching up to the last filename.
So, it should probably be '.*?'.
However, if the filenames are different then it shouldn't have matched.
Another thing is you should in general stop it from running past the next [alt] with
something like '[^\[\]]*'
Edit:
RegExp.escape('![') + '.*' + RegExp.escape(']') + RegExp.escape('(') + '.*' + RegExp.escape(fileName) + RegExp.escape(')'), 'i');
is the culprit.
Try
RegExp.escape('![') + '[^\]]*' + RegExp.escape(']') + RegExp.escape('(') + '[^\[\]]*?' + RegExp.escape(fileName) + RegExp.escape(')'), 'i');