正则表达式根据条件将字符串添加到每个单词的开头

时间:2020-02-23 18:30:08

标签: javascript regex replace

我有一个看起来像这样的字符串

someString = "#3Hello there! How many #4candies did you sell today? Do have any #4candies left?"

lookupDict = {"Hello there": "#3", "candies": "#4"}

现在,我想用someString替换字符串#0中不在字典lookupDict中的所有术语。我不能用空格" "分割,因为这会使诸如Hello there之类的某些术语以两个不同的词Hellothere出现,并且永远不会符合我的条件。< / p>

现在,我知道要应用基本的正则表达式,该正则表达式将在每个单词的前面添加一个#0。例如类似

let regex = /(\b\w+\b)/g;

someString = someString.replace(regex, '#0$1'));

但是那样会盲目地将#0添加到每个术语中,而不会在字典lookupDict中查找。

有什么方法可以将正则表达式与字典中的查找结合起来并相应地分配#0吗?基本上,最终结果将类似于

someString = "#3Hello there! #0How #0many #4candies #0did #0you #0sell #0today? #0Do #0have #0any #4candies #0left?"

注意:此处的空格可以视为单词边界。

3 个答案:

答案 0 :(得分:1)

通过这种方式,不必担心lookupDict键的长度或其他任何事情:

let someString =
  "#3Hello there! How many #4candies did you sell today? #3Hello there! Do have any #4candies left?#3Hello there! #7John Doe! some other text with having #7John Doe person again";

const lookupDict = { "Hello there": "#3", candies: "#4", "John Doe": "#7" };

Object.keys(lookupDict).map((key, i) => {
  const regex = new RegExp(key, "g");
  someString = someString.replace(regex, lookupDict[key]); // replace each key to the value: Hello world => #3
});

someString = someString.replace(/ /gi, " #0"); // replace each space

Object.keys(lookupDict).map((key, i) => {
  const regex = new RegExp(lookupDict[key] + lookupDict[key], "g");
  someString = someString.replace(regex, `${lookupDict[key]}${key}`); // role back the value to key+value
});

someString = someString.replace(/#0#/gi, "#"); // replace #0 for each lookupDict key value

console.log(someString, '<TheResult/>');

答案 1 :(得分:1)

您可以使用以下逻辑:

  • 构建需要跳过的,关联数组的valuekey串联的子字符串数组
  • 由于单词边界可能不适用于包含空格的短语,因此请按长度降序排列项目
  • 编译一个包含两种选择的正则表达式模式:第一个将匹配捕获组所包围的数组项(转义为用于regex模式),另一个将匹配其余的“单词”
  • 找到匹配项后,检查第1组是否匹配。如果第1组匹配,则只需返回匹配值,否则,将#0添加到匹配值中。

这里是实现:

let someString = "#3Hello there! How many #4candies did you sell today? Do have any #4candies left? #0how #0much";
const lookupDict = {"Hello there": "#3", "candies": "#4", "how": "#0", "much": "#0"};
let patternDict = [];                             // Substrings to skip
for (var key in lookupDict) {                     
  patternDict.push( `${lookupDict[key]}${key}` ); // Values + keys
}
patternDict.sort(function(a, b){                  // Sorting by length, descending
  return b.length - a.length;
});
var rx = new RegExp("(?:^|\\W)(" + patternDict.map(function(m) { // Building the final pattern
    return m.replace(/[-\/\\^$*+?.()|[\]{}]/g, '\\$&');}
  ).join("|") + ")(?!\\w)|\\S+", "gi");
// rx = /(?:^|\W)(#3Hello there|#4candies|#0much|#0how)(?!\w)|\S+/gi
someString = someString.replace(rx, (x, y) => y ? x : `#0${x}` );
console.log(someString);
// => #3Hello there! #0How #0many #4candies #0did #0you #0sell #0today? #0Do #0have #0any #4candies #0left? #0how #0much

正则表达式看起来像

/(?:^|\W)(#3Hello there|#4candies|#0much|#0how)(?!\w)|\S+/gi

请参见regex demo(已选择PHP选项以绿色突出显示组)。

详细信息

  • (?:^|\W)-一个非捕获组,它匹配字符串(^或(|)的任何非单词char(=除ASCII字母,数字之外的char)或_
  • (#3Hello there|#4candies|#0much|#0how)-捕获与任何lookupDict串联值+键相匹配的组1
  • (?!\w)-如果在当前位置的右侧紧邻有单词char,则否定超前行为将使匹配失败
  • |-或
  • \S+-1个以上非空格字符。

答案 2 :(得分:-1)

您可以将函数作为第二个参数传递给.replace并检查字典中的匹配令牌

我将正则表达式更改为不包含#的结果

Hello there有问题,一个学期可以持续多久?最多2个字?

someString = "#3Hello there! How many #4candies did you sell today? Do have any #4candies left?"

let regex = /(?<!#)(\b\w+\b)/g;

someString = someString.replace(regex, x => {
// check x in dict
	return `#0${x}`
});
console.log(someString)