How to combine overlapping keywords with regex

This example is displayed only sam. How to make him find both sam , and so samwise?

var regex = /sam|samwise|merry|pippin/g;
var string = 'samwise gamgee';
var match = string.match(regex);
console.log(match);

Note. This is a simple example, but my real regular expressions are created by connecting 500 keywords in time, so it’s too cumbersome to look for all overlapping ones and make a special case for them with something like /sam(wise)/. Another obvious solution that I can think of is to simply repeat all the keywords individually, but I think it should be a quick and elegant solution with one regular expression.

+4
source share
5 answers

lookahead regex :

var regex = /(?=(sam))(?=(samwise))/;
var string = 'samwise';
var match = string.match( regex ).filter(Boolean);
//=> ["sam", "samwise"]
  • g (global) .
  • filter(Boolean) .
+2

map indexOf() :

var string = 'samwise gamgee';
var substr = ['sam', 'samwise', 'merry', 'pippin'];

var matches = substr.map(function(m) {
  return (string.indexOf(m) < 0 ? false : m);
}).filter(Boolean);

console.log(matches);

[ "sam", "samwise" ]

, , . , . , , ... exec:

var matches = substr.map(function(v) {
  var re = new RegExp("\\b" + v, "i"); var m = re.exec(string); 
  return (m !== null ? m[0] : false);
}).filter(Boolean);

i -flag () \b .

+1

, -, :

function quotemeta(s) {
    return s.replace(/\W/g, '\\$&');
}

let keywords = ['samwise', 'sam'];

let subsumed_by = {};
keywords.sort();
for (let i = keywords.length; i--; ) {
    let k = keywords[i];
    for (let j = i - 1; j >= 0 && k.startsWith(keywords[j]); j--) {
        (subsumed_by[k] = subsumed_by[k] || []).push(keywords[j]);
    }
}

keywords.sort(function (a, b) b.length - a.length);
let re = new RegExp('(?=(' + keywords.map(quotemeta).join('|') + '))[\\s\\S]', 'g');

let string = 'samwise samgee';

let result = [];
let m;
while (m = re.exec(string)) {
    result.push(m[1]);
    result.push.apply(result, subsumed_by[m[1]] || []);
}

console.log(result);
0

:

var re = /((sam)(?:wise)?)/;
var m = 'samwise'.match(re); // gives ["samwise", "samwise", "sam"]
var m = 'sam'.match(re);     // gives ["sam", "sam", "sam"]

.

0

, , :

\b(sam|samwise|merry|pippin)\b

, , ? :

(sam|samwise|merry|pippin)(?=\w+\b)

, , , .

0

Source: https://habr.com/ru/post/1598491/


All Articles