查找字符串中的查询匹配项

时间:2019-07-03 17:35:29

标签: javascript regex autocomplete

我有一个任务,根据查询来计算要突出显示在文本中的字符。 假设给定的文本为"London, United Kingdom",查询为"lond"。然后结果应该是[[0, 4]]

我有一个简单的实现,可以很好地解决这种情况:

// ...
.reduce((result, word) => {
  const wordLen = word.length;
  const prefix = wordCharacterRegex.test(word[0]) ? "\\b" : "";
  const regex = new RegExp(prefix + escapeRegexCharacters(word), "i");
  const index = text.search(regex);

  if (index > -1) {
    result.push([index, index + wordLen]);

    text =
      text.slice(0, index) +
      new Array(wordLen + 1).join(" ") +
      text.slice(index + wordLen);
  }

  return result;
}, [])
// ...

,但是如果文本为"EC2V 6DB, London, United Kingdom"并且查询为"ec2v6db",则该文本将不起作用,因为正则表达式将为/\bec2v6db/i。 那么,如何更改我的代码并解决问题?

1 个答案:

答案 0 :(得分:1)

首先,如果第一个字符是单词char,则添加的单词边界应该与非单词char保持一致:如果在单词char之前添加\b,请添加\B在非单词字符之前获得相同的行为。

const prefix = wordCharacterRegex.test(word[0]) ? "\\b" : "\\B";

然后,尚不清楚escapeRegexCharacters方法的外观,但可以在其中将\s*插入关键字的每个字符之间。

function escapeRegexCharacters(s) {
    var res = s.replace(/([-\/\\^$*+?.()|[\]{}])|[\s\S]/g, (m,g) => (g ? "\\" + g : m) + "\\s*");
    return res.substring(0, res.length -3);
}

这是一个演示:

let word = "ec2v6db"; // lond is checked
let text = "EC2V 6DB, London, United Kingdom";
const wordCharacterRegex = /\w/;

function escapeRegexCharacters(s) {
    var res = s.replace(/([-\/\\^$*+?.()|[\]{}])|[\s\S]/g, (m,g) => (g ? "\\" + g : m) + "\\s*");
    return res.substring(0, res.length -3);
}

const prefix = wordCharacterRegex.test(word[0]) ? "\\b" : "\\B";
const regex = new RegExp(prefix + escapeRegexCharacters(word), "i");

// Replacing text with spaces
console.log(text.replace(regex, m => " ".repeat(m.length)));
// => "        , London, United Kingdom"

// Adding tags around the match
console.log(text.replace(regex, "<highlight>$&</highlight>"));

// Getting the indices:
let match = regex.exec(text);
if (match) {
   console.log([match.index, match.index+match[0].length]);
}