Regex to match markdown image pattern with the given filename - javascript

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');

Related

How to turn a String with square brackets and forward slashes + variables into a regex?

I've tried to get my head around regex, but I still can't get it.
I want to turn the following String + some variables into a regex:
"[url href=" + objectId + "]" + objectId2 + "[/url]"
I tried the following, since I read somewhere that brackets and slashes need to be escaped:
/\[url href=/ + objectId + /\]/ + objectId2 + /\[\/\url\]/g
But that isn't working.
I want to use it to replace the whole expression into HTML wherever it matches in a String.
You are correct that brackets and backslashes need to be escaped in a regular expression, but you can't create a regex by adding together regex literals like your /\[url href=/ + objectId + /\]/ attempt. To build a regex dynamically like that you have to use string concatenation and pass the result to new RegExp(). So as a starting point for your text you'd need this:
new RegExp("\\[url href=" + objectId + "\\]" + objectId2 + "\\[/url\\]")
Note all of the double-backslashes - that's because backslashes need to be escaped in string literals, so "\\[" creates a string containing a single backslash and then a bracket, which is what you want in your regex.
But if you want to extract the matched href and content for use in creating an anchor then you need capturing parentheses:
new RegExp("\\[url href=(" + objectId + ")\\](" + objectId2 + ")\\[/url\\]")
But that's still not enough for your purposes because objectId and objectId2 could (or will, given the first is a url) contain other characters that need to be escaped in a regex too, e.g., .+?(), etc. So here's a function that can escape all of the necessary characters:
function escapeStringForRegex(s) {
return s.replace(/[-\/\\^$*+?.()|[\]{}]/g, '\\$&');
}
We can't just call that function on the whole thing, because you need unescaped parentheses for your capturing sub matches, so just call it on the two variables:
var urlRegex = new RegExp("\\[url href=("
+ escapeStringForRegex(objectId)
+ ")\\]("
+ escapeStringForRegex(objectId2)
+ ")\\[/url\\]");
Kind of messy, but seems to do the job as you can see here:
function escapeStringForRegex(s) {
return s.replace(/[-\/\\^$*+?.()|[\]{}]/g, '\\$&');
}
function createAnchors(str, objectId, objectId2) {
var urlRegex = new RegExp("\\[url href=(" + escapeStringForRegex(objectId) + ")\\](" + escapeStringForRegex(objectId2) + ")\\[/url\\]", "g");
return str.replace(urlRegex, "<a href='$1'>$2</a>");
}
document.querySelector("button").addEventListener("click", function() {
var str = document.getElementById("input").value;
var objectId = document.getElementById("objectId").value;
var objectId2 = document.getElementById("objectId2").value;
document.getElementById("output").value =
createAnchors(str, objectId, objectId2);
});
textarea { width : 100%; height: 80px; }
Input:<br><textarea id="input">This is just some text that you can edit to try things out. [url href=http://test.com.au?param=1]Test URL[/url]. Thanks.</textarea>
ObjectId:<input id="objectId" value="http://test.com.au?param=1"><br>
ObjectId2:<input id="objectId2" value="Test URL"><br>
<button>Test</button>
<textarea id="output"></textarea>
Note that the above searches only for [url]s in your string that have the particular href and content specified in the objectId and objectId2 variables. If you just want to change all [url]s into anchors regardless of what href and text they contain then use this:
.replace(/\[url href=([^\]]+)\]([^\]]+)\[\/url\]/g, "<a href='$1'>$2</a>")
Demo:
function escapeStringForRegex(s) {
return s.replace(/[-\/\\^$*+?.()|[\]{}]/g, '\\$&');
}
function createAnchors(str) {
return str.replace(/\[url href=([^\]]+)\]([^\]]+)\[\/url\]/g, "<a href='$1'>$2</a>");
}
document.querySelector("button").addEventListener("click", function() {
var str = document.getElementById("input").value;
document.getElementById("output").value = createAnchors(str);
});
textarea { width : 100%; height: 80px; }
Input:<br><textarea id="input">Testing. [url href=http://test.com.au?param=1]Test URL[/url]. Thanks. Another URL: [url href=https://something.com/test?param=1&param2=123]Test URL 2[/url]</textarea>
<button>Test</button>
<textarea id="output"></textarea>
It's like:
var rx = new RegExp('\\[url\\shref='+objectId+'\\]'+objectId2+'\\[\\/url\\]');
new RegExp("[url href=" + objectId + "]" + objectId2 + "[\url]")
https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/RegExp

Regex to get word started with # in javascript

I have a problem replace certain words started with #. I have the following code
var x="#google",
eval("var pattern = /" + '\\b' + x + '\\b');
txt.replace(pattern,"MyNewWord");
when I use the following code it works fine
var x="google",
eval("var pattern = /" + '\\b' + x + '\\b');
txt.replace(pattern,"MyNewWord");
it works fine
any suggestion how to make the first part of code working
ps. I use eval because x will be a user input.
The problem is that \b represents a boundary between a "word" character (letter, digit, or underscore) and a "non-word" character (anything else). # is a non-word character, so \b# means "a # that is preceded by a word character" — which is not at all what you want. If anything, you want something more like \B#; \B is a non-boundary, so \B# means "a # that is not preceded by a word character".
I'm guessing that you want your words to be separated by whitespace, instead of by a programming-language concept of what makes something a "word" character or a "non-word" character; for that, you could write:
var x = '#google'; // or 'google'
var pattern = new RegExp('(^|\\s)' + x);
var result = txt.replace(pattern, '$1' + 'MyNewWord');
Edited to add: If x is really supposed to be a literal string, not a regex at all, then you should "quote" all of the special characters in it, with a backslash. You can do that by writing this:
var x = '#google'; // or 'google' or '$google' or whatever
var quotedX = x.replace(/[^\w\s]/g, '\\$&');
var pattern = new RegExp('(^|\\s)' + quotedX);
var result = txt.replace(pattern, '$1' + 'MyNewWord');
Make you patter something like this:
/(#)?\w*/
If you want to make a Regular Expression, try this instead of eval:
var pattern = new RegExp(x);
Btw the line:
eval("var pattern = /" + '\\b' + x + '\\b');
will make an error because of no enclose pattern, should be :
eval("var pattern = /" + '\\b' + x + '\\b/');
How about
var x = "#google";
x.match(/^\#/);

Javascript: replace inside a replace

My input is many lines of text that looks like this:
a.b.c.d.e (f:g)
I need to turn this into
a.b.c.d.e (a/b/c/d/e/f?g)
Note that the dotted part (a.b.c.d.e) can have varying numbers of elements, so sometimes it'll be q.r.s.t, sometimes u.v.w.x.y.z and so on. I have a replace() that will give me (a.b.c.d.e.f?g), but what I need is then to turn all those .s into /s in the result.
Is there a way to do a replace inside a replace? Or should I just call replace() on the string twice?
Sorry if this question is poorly worded, I'm not awfully well versed at regular expressions in javascript.
A very crazy way of doing it:
var str = "a.b.c.d.e (f:g)";
var re = /([^\s]+)\s\(([^:]+):([^\)]+)\)/;
var newStr = str.replace(re, function(a,b,c,d){ return b + " (" + b.replace(/\./g,"/") + "/" + c + "?" + d + ")"; });
jsfiddle
You need to chain the calls to replace() one after the other.
var result = source.replace("foo", "bar").replace("oof", "rab");
A saner way :) http://jsfiddle.net/smfPU/
input = "a.b.c.d.e.w.x.y.z (f:g:h)";
output = input.replace(/:/g, "?");
outputparts = output.split("(");
left = outputparts[0];
middle = left.replace(/\./g, "/").trim();
right = outputparts[1];
output = left + "(" + middle + "/" + right;
document.write(output);

javascript find and replace a dynamic pattern in a string

I have a dynamic pattern that I have been using the code below to find
var matcher = new RegExp("%" + dynamicnumber + ":", "g");
var found = matcher.test(textinput);
I need the pattern to have a new requirement, which is to include an additional trailing 5 characters of either y or n. And then delete it or replace it with a '' (nothing).
I tried this syntax for the pattern, but obviously it does not work.
var matcher = new RegExp("%" + dynamicnumber + ":" + /([yn]{5})/, "g");
Any tip is appreciated
TIA.
You should only pass the regex string into the RegExp c'tor :
var re = new RegExp("%" + number + ":" + "([yn]{5})", "g");
var matcher = new RegExp("(%" + number + ":)([yn]{5})", "g");
Then replace it with the contents of the first capture group.
Use quotes instead of slashes:
var matcher = new RegExp("%" + number + ":([yn]{5})", "g");
Also, make sure that dynamicnumber or number are valid RegExps. special characters have to be prefixed by a double slash, \\, a literal double slash has to be written as four slashes: \\\\.

Simple regex: how do I say: "it's okay to have an " s " or " es " or " 's " at the end of the word, match those too."?

I'm using Jquery(don't know if that's relevant), here's the regex:
var re = new RegExp('\\b' + a_filter + '\\b');
So it matches whole words in the variabe a_filter which has a bunch of words in it. Right now it will match 'wrench', but not 'wrenches'. It will match 'chair', but not 'chairs', it will match "john" but not "john's". I've been trying but I can't figure it out.
Can someone please help me adjust my regex above to allow for these at the end of the word?
s es 's are what I want to allow at the end of a word match, so i don't have to include every single possible variation of each word. I think that's all the word endings that there really are that someone would type, if you know more, it would be great to get help, THANKS!
EDIT: here's my jsfiddle, maybe I had a_filter mixed up with filter_tags, I think i'm doing it backwards, ugh. ???
http://jsfiddle.net/nicktheandroid/mMTsc/18/
I have a group of your endings after the filter concatenation, with ? to require 0 or 1 match.
var a_filter = "wrench";
var re = new RegExp('\\b' + a_filter + '(s|es|\'s)?\\b');
alert( re.test("wrench's") );
Example: http://jsfiddle.net/qctAG/ (alert() warning. you'll get 4 of them)
You want something that looks like this:
var re = new RegExp('\\b' + a_filter + '(s|es|\'s)?\\b');
Of course, that will not match all plurals (e.g. oxen, geese) and it will match words that don't exist (e.g. sheeps).
This works for me...assuming you have an array!
var a_filter = ["wrench","wrenches","wrench's"];
for(var i=0; i < a_filter.length; i++){
var re = new RegExp('\^' + a_filter[i] + '\$');
document.write(re.test("wrench's") + " " + a_filter[i] + "<br />");
}
Here is the fiddle: http://jsfiddle.net/XCARd/2/
Play with the re.test() to see it match.

Categories