Search code examples
javascriptregexregex-negation

Detect tags in a logical expression string


Description:

In my Javascript code I have a logical expression as a string, like in the example below:

'foo && !bar || baz'

Where foo, bar and baz are the names of some tags within my app.

A tag can contain lowercase, uppercase letters, numbers and special characters (+, - , *, #, etc). So the following strings may be valid tags: foo-bar, foo#, f*oo.

The possible logical operators are: || (OR), && (AND) and ! (NOT).

Requirement:

I need to get only the tags from the string above, as an array:

['foo', 'bar', 'baz']

The code I've tried: I tried to use the regex /&&|\|/ to get the logical operators, and then try to invert the logical expression, but without success.

Other examples:

foo && bar => expected result ['foo', 'bar']

foo1 || bar1 => expected result ['foo1', 'bar1']

foo+ && !bar& => expected result ['foo+', 'bar&']

foo && bar || baz => expected result ['foo', 'bar', 'baz']


Solution

  • You can simply split on the operators:

    var text = 'foo && bar& || !baz';
    var regex = / *(?:&&|\|\||!) */;
    var tags = text
      .split(regex)     // split on operators
      .filter(Boolean); // filter out empty items
    console.log('text: ' + text);
    console.log('tags: ' + JSON.stringify(tags));

    Output:

    text: foo && bar& || !baz
    tags: ["foo","bar&","baz"]
    

    This test input covers the corner case of consecutive operators (|| and !), and a single & as part of the tag name.

    Explanation of regex used for split:

    • * - expect optional space
    • (?:&&|\|\||!) -followed by all ORed operators; (?:...) is a non-capturing group (split includes captured groups in the resulting array)
    • * - followed by optional spaces