0

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.

user3926061
  • 13
  • 1
  • 6
  • 1
    `new RegExp("\\[url href=" + objectId + "\\]" + objectId2 + "\\[\\\\url\\]")` - would be a start, but you'd need to escape whatever is in `objectId1` and `object2` - what characters can they contain? – nnnnnn Aug 18 '16 at 00:25
  • @nnnnnn Every possible character that a URL can have. Numbers, letters, symbols, etc. – user3926061 Aug 18 '16 at 00:30
  • Passing into `new RegExp()` is the way to use strings. – StackSlave Aug 18 '16 at 00:32
  • 1
    http://stackoverflow.com/questions/3561493/is-there-a-regexp-escape-function-in-javascript - for escaping the values in the variables. Also note that if you want to change the matched text into HTML, presumably an anchor element, you'd need to add some `()` sub matches for `objectId` and `objectId2` in order to extract the relevant details. – nnnnnn Aug 18 '16 at 00:33

3 Answers3

0

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>
nnnnnn
  • 147,572
  • 30
  • 200
  • 241
-1

It's like:

var rx = new RegExp('\\[url\\shref='+objectId+'\\]'+objectId2+'\\[\\/url\\]');
StackSlave
  • 10,613
  • 2
  • 18
  • 35
  • This won't work, because backslashes have meaning in string literals. – nnnnnn Aug 18 '16 at 00:36
  • I thought those were quotes. You changed your comment. – StackSlave Aug 18 '16 at 00:38
  • Oh, sorry. Before I edited they were backticks containing a single backslash, but that didn't display properly so I replaced it with the word "backslashes". (You'd need four in a row for `\\\\url`, except that the OP has since edited the question to make it `/url`.) – nnnnnn Aug 18 '16 at 00:39
  • The thing is the strings are evaluated before they are concatenated to form the expression you desire. – StackSlave Aug 18 '16 at 00:42
  • Yes. Which is why you'd need the string `'\\\\url'` to create a regex with `\\url`. (Except the OP changed it to `/url` so that doesn't need escaping in a string, only in a regex literal.) – nnnnnn Aug 18 '16 at 00:44
-2
new RegExp("[url href=" + objectId + "]" + objectId2 + "[\url]")

https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/RegExp

jshawl
  • 3,315
  • 2
  • 22
  • 34
  • 2
    This won't work. You'd need to escape the square brackets and double-escape the backslash, and possibly escape whatever is is in `object1` and `objectId2`... – nnnnnn Aug 18 '16 at 00:24