最新消息:雨落星辰是一个专注网站SEO优化、网站SEO诊断、搜索引擎研究、网络营销推广、网站策划运营及站长类的自媒体原创博客

I would like to mimick conditionals in javascript regex - Stack Overflow

programmeradmin3浏览0评论

This is what I have so far...

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])
  }
}

I am swapping (?(n)a|b) for ((?!\n)a|\nb) where n is a number, and a and b are strings. This seems to work fine - however, I am aware that it is a big fat hack.

Is there a better way to approach this problem?

This is what I have so far...

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])
  }
}

I am swapping (?(n)a|b) for ((?!\n)a|\nb) where n is a number, and a and b are strings. This seems to work fine - however, I am aware that it is a big fat hack.

Is there a better way to approach this problem?

Share Improve this question asked Feb 22, 2013 at 11:01 Billy MoonBilly Moon 58.6k26 gold badges147 silver badges243 bronze badges 4
  • 3 Well... it'd be much easier if you told us what is your goal. – oleq Commented Feb 22, 2013 at 11:04
  • well... s(at)?u(?(1)r|n)day is invalid regex in javascript, which does not support conditionals like (?(1)r|n). My intermediary regex swaps out that conditional, for a pattern which mimicks it, and works in javascript... ((?!\1)r|\1n) but although it seems to work, I think this is not the right approach – Billy Moon Commented Feb 22, 2013 at 11:11
  • My goal, is to be able to write conditionals in the usual manner, and automatically modify the regex into a form that can work in javascript – Billy Moon Commented Feb 22, 2013 at 11:13
  • 3 Why do you want to do that? Far easier to chose the regex to use in code. (Are you suffering from an X-Y problem? You are trying to solve something (X) and have e up with regex (Y) but they don't quite do what you want. Rather than force regex to solve Y, you would be better off looking at alternatives approaches to your real problem (X)). – Richard Commented Feb 22, 2013 at 11:19
Add a ment  | 

1 Answer 1

Reset to default 16

In the specific case of your regex, it is much simpler and more readable to use alternation:

(?:sunday|saturday)

Or you can create alternation only between the 2 positions where the conditional regex is involved (this is more useful in the case where there are many such conditional expressions, but only refers to the nearby capturing group). Using your case as an example, we will only create the alternation for un and atur since only those are involved in the condition:

s(?:un|atur)day

There are 2 mon types of conditional regex. (There are more exotic stuffs supported by Perl regular expression, but those requires support for features that JavaScript regular expression or other mon regex engine doesn't have).

  1. The first type is where an explicit pattern is provided as condition. This type can be mimicked in JavaScript regex. In the language that supports conditional regex, the pattern will be:

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

    In JavaScript, you can mimic it with look-ahead, with the (obvious) assumption that the original conditional-pattern is a look-ahead:

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

    The negative look-ahead is necessary, to prevent the cases where the input string passes the conditional-pattern and fail in the yes-pattern, but it can match the no-pattern. It is safe to do so, because positive look-around and negative look-around are exact opposite of each other logically.

  2. The second type is where a reference to a capturing group is provided (name or number), and the condition will be evaluated to true when the capturing group has a match. In such case, there is no simple solution.

    The only way I can think of is by duplication, as what I have done with your case as an example. This of course reduces the maintainability. It is possible to pose you regex by writing them in parts (in literal RegExp), retrieve the string with source attribute, then concatenate them together; this will allow for changes to propagate to other duplicated parts, but makes it harder to understand the regex and/or make major modification to it.

References

  • Alternation Constructs in Regular Expression - .NET - Microsoft
  • re package in Python: Ctrl+F for (?(
  • perlre - Perl regular expression: Ctrl+F for (?(
发布评论

评论列表(0)

  1. 暂无评论