0

I am trying to write a regex to split an input string based on first and last character.

e.g

input : "$(tag1)sample$(tag2)"

output : ["$tag1", "sample", "$tag2"]

var input = $(tag1)sample$(tag2);
var splitStrings = input.split(/^$|)$/);

But getting following error :

Invalid regular expression: /^$|)$/: Unmatched ')'.

shA.t
  • 16,580
  • 5
  • 54
  • 111
geekops
  • 505
  • 8
  • 21

3 Answers3

1

Note that $ and ) are special regex metacharacters that - if you need to match these chars literally - must be escaped or put into [...] character classes.

However, escaping them won't work for you in this case. You may split with /(\$\([^()]+\))/, remove empty entries and remove the parentheses in qualifying matches:

var input = "$(tag1)sample$(tag2)";
var splitStrings = input.split(/(\$\([^()]+\))/);
console.log(
  splitStrings.map(function(x) {
     return x.replace(/^\$\((.*)\)$/, '$$$1');
    }
  ).filter(Boolean)
);

The point here is:

  • Splitting with (\$\([^()]+\)), we get an array of $(...) and all the chunks of text that do not match this pattern
  • We need to remove empty strings from the array that usually come with this kind of a split operation (thus, filter(Boolean) or similar should be used)
  • We need to replace $( and ) with $ in the entries that were matched with the splitting pattern
  • In .replace(/^\$\((.*)\)$/, '$$$1'), the replacement has 3 $s, because to replace with a single $, we need to double it in the string replacement pattern, and the 3rd one forms a backreference $1.
Wiktor Stribiżew
  • 607,720
  • 39
  • 448
  • 563
0

Escape the ) character like so: /^$|\)$/

) is a reserved symbol in Regex, meaning you have to tell the engine to treat it like a character, which is what \ does.

Jeff Huijsmans
  • 1,388
  • 1
  • 14
  • 35
0

The reason for the error is that you have to escape characters that have special meaning in regular expressions, like ) and $.

But just fixing that won't get you to the output you're looking for, where you want to split on the special tags, remove the () in the tags, and keep them. I don't think there's a single regex solution for this with JavaScript's regexes (perhaps someone smarter than I knows a way, but with the transforming $(tag1) to $tag1 I'm not getting there). But we can get there with a couple of replaces and a split:

var input = "$(tag1)sample$(tag2)";
var splitStrings = input.replace(/\$\(([^)]+)\)/g, "\t$$$1\t")
                        .replace(/(?:^\t+)|(?:\t+$)/g, '')
                        .split(/\t+/);
console.log(splitStrings);

The first replace transforms $(tag1) to \t$tag1\t (e.g., puts tabs around it and removes the ()). The second replace gets rid of any leading and trailing tabs. Then the split splits on any sequence of tabs.

Of course, if tabs may occur in the string and you want to keep them, just replace them with anything else that suits.

T.J. Crowder
  • 1,031,962
  • 187
  • 1,923
  • 1,875