我想在javascript正则表达式中模仿条件

时间:2013-02-22 11:01:06

标签: javascript regex

这就是我到目前为止......

var regex_string = "s(at)?u(?(1)r|n)day"
console.log("Before: "+regex_string)
var regex_string = regex_string.replace(/\(\?\((\d)\)(.+?\|)(.+?)\)/g,'((?!\\$1)$2\\$1$3)')
console.log("After: "+regex_string)
var rex = new RegExp(regex_string)

var arr = "thursday tuesday thuesday tursday saturday sunday surday satunday monday".split(" ")
for(i in arr){
  var m
  if(m = arr[i].match(rex)){
    console.log(m[0])
  }
}

我正在(?(n)a|b)替换((?!\n)a|\nb),其中n是一个数字,ab是字符串。这似乎工作正常 - 但是,我知道这是一个很大的黑客。

有没有更好的方法来解决这个问题?

1 个答案:

答案 0 :(得分:12)

在你的正则表达式的特定情况下,使用交替更简单,更易读:

(?:sunday|saturday)

或者您可以仅在涉及条件正则表达式的2个位置之间创建交替(这在有许多此类条件表达式但仅指向附近捕获组的情况下更有用)。以您的案例为例,我们只会为unatur创建替换,因为只有那些涉及条件:

s(?:un|atur)day

有两种常见类型的条件正则表达式。 (Perl正则表达式支持更多奇特的东西,但这些东西需要支持JavaScript正则表达式或其他常见正则表达式引擎所没有的功能。)

  1. 第一种类型是作为条件提供显式模式的位置。这种类型可以在JavaScript正则表达式中模仿。在支持条件正则表达式的语言中,模式将为:

    (?(conditional-pattern)yes-pattern|no-pattern)
    

    在JavaScript中,您可以使用前瞻模仿它,并且(明显的)假设原始conditional-pattern是预见的:

    ((?=conditional-pattern)yes-pattern|(?!conditional-pattern)no-pattern)
    

    负面预测是必要的,以防止输入字符串通过conditional-pattern并在yes-pattern中失败的情况,但它可以匹配no-pattern。这样做是安全的,因为积极的环顾四周和消极的环顾在逻辑上完全相反。

  2. 第二种类型是提供对捕获组的引用(名称或编号),并且当捕获组具有匹配项时,条件将被评估为true。在这种情况下,没有简单的解决方案。

    我能想到的唯一方法就是复制,就像我以你的案例所做的那样。这当然会降低可维护性。可以通过在部分(在文字RegExp中)编写它们来组成正则表达式,检索具有source属性的字符串,然后将它们连接在一起;这将允许更改传播到其他重复的部分,但是更难理解正则表达式和/或对其进行重大修改。

  3. <强>参考