Detect tags in a logical expression string

Viewed 87

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']

2 Answers

You can build your solution in 2 steps as this:

  1. Use replace to remove operators using /(?:\|\||&&|\B!)/g
  2. Split remaining string by whitespace

const arr=['foo! && bar',
'foo1 || bar1',
'foo+ && !bar&',
'foo && bar || baz']

const re = /(?:\|\||&&|\B!)/g

res = []
arr.forEach(el => res.push(el.replace(re, "").split(/\s+/)))

console.log(res)

Regex (?:\|\||&&|\B!) matches || or && or ! that is not after a word character.

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
Related