user3926061 user3926061 - 3 months ago 20
jQuery Question

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.

Answer

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&amp;param2=123]Test URL 2[/url]</textarea>
<button>Test</button>
<textarea id="output"></textarea>