【问题标题】:How to manipulate the pattern of a RegExp dynamically?如何动态操作 RegExp 的模式?
【发布时间】:2018-08-23 02:25:33
【问题描述】:

我有一个文本数组 lines 和一个 terms 数组,每个 term 行包含一对单词。例如,terms 数组可能类似于:

blue, red
high, low
free, bound
 ...

对于lines数组中的每一行,我需要遍历所有terms的列表,并用第二个单词替换第一个单词的每个出现;全局且不区分大小写。例如,行

The sky is Blue and High, very blue and high, yet Free

会变成

The sky is red and low, very red and low, yet bound

这样的代码:

function filter(lines,terms){
    for (line of lines){
        for (term of terms){
             tofind    = term[0]; //this is a string not RegExp
                                  //still needs the 'gi' flags
             toreplace = term[1];
             line      = line.replace(tofind,toreplace);
        }

    }
}

这是错误的,因为tofind 需要是 RegExp (pattern, 'gi') 并且需要在循环内的每次迭代中动态生成。

如果tofind 字符串是静态的,我们可以这样做:

line = line.replace(/some-static-text-here/gi,toreplace)

我试过line.replace(new RegExp(tofind,'gi'),toreplace),但这会引发错误Invalid regular expression: /*Contains/: Nothing to repeat

所以,问题是:如何在循环内动态修改 RegExp 对象的模式?

【问题讨论】:

  • 看来tofind* 开头,这使得它成为无效的正则表达式(因为* 是一个量词,它之前没有任何东西可以应用) .除此之外,生成new RegExpes 应该没有问题。
  • 当您尝试line.replace(new RegExp(tofind,'gi'),toreplace) 时,tofind 的值是多少?
  • RegExp() 构造函数是您问题的答案,但它引出了后续问题:如何“清理”纯字符串以使其成为有效的正则表达式。这更复杂。

标签: javascript regex


【解决方案1】:

如果 terms 数组只包含字母数字值,您可以构建新的正则表达式。

function filter(lines, terms) {
    return lines.map(s => 
        terms.reduce((r, t) => r.replace(new RegExp(t[0], 'gi'), t[1]), s));
}

console.log(filter(['The sky is Blue and High, very blue and high, yet Free'], [['blue', 'red'], ['high', 'low'], ['free', 'bound']]));

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-11-12
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多