这就是我到目前为止......
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
是一个数字,a
和b
是字符串。这似乎工作正常 - 但是,我知道这是一个很大的黑客。
有没有更好的方法来解决这个问题?
答案 0 :(得分:12)
在你的正则表达式的特定情况下,使用交替更简单,更易读:
(?:sunday|saturday)
或者您可以仅在涉及条件正则表达式的2个位置之间创建交替(这在有许多此类条件表达式但仅指向附近捕获组的情况下更有用)。以您的案例为例,我们只会为un
和atur
创建替换,因为只有那些涉及条件:
s(?:un|atur)day
有两种常见类型的条件正则表达式。 (Perl正则表达式支持更多奇特的东西,但这些东西需要支持JavaScript正则表达式或其他常见正则表达式引擎所没有的功能。)
第一种类型是作为条件提供显式模式的位置。这种类型可以在JavaScript正则表达式中模仿。在支持条件正则表达式的语言中,模式将为:
(?(conditional-pattern)yes-pattern|no-pattern)
在JavaScript中,您可以使用前瞻模仿它,并且(明显的)假设原始conditional-pattern
是预见的:
((?=conditional-pattern)yes-pattern|(?!conditional-pattern)no-pattern)
负面预测是必要的,以防止输入字符串通过conditional-pattern
并在yes-pattern
中失败的情况,但它可以匹配no-pattern
。这样做是安全的,因为积极的环顾四周和消极的环顾在逻辑上完全相反。
第二种类型是提供对捕获组的引用(名称或编号),并且当捕获组具有匹配项时,条件将被评估为true。在这种情况下,没有简单的解决方案。
我能想到的唯一方法就是复制,就像我以你的案例所做的那样。这当然会降低可维护性。可以通过在部分(在文字RegExp中)编写它们来组成正则表达式,检索具有source
属性的字符串,然后将它们连接在一起;这将允许更改传播到其他重复的部分,但是更难理解正则表达式和/或对其进行重大修改。
<强>参考强>
(?(
(?(