如何有条件的正则表达式

我想要一个正则表达式做一件事,如果它有3个实例. 在字符串中,如果它有超过3个实例,则为其他内容。

例如

 aaa.bbb.ccc.ddd // one part of the regex aaa.bbb.ccc.ddd.eee // the second part of the regex 

我如何在jsc#实现这一目标?

就像是

 ?(\.){4} then THIS else THAT 

在正则表达式内……

更新

好吧基本上我正在做的是这样的:

我想将任何给定的System.Uri切换到扩展方法中的另一个子域。

我遇到的问题是我的域名通常是http://subdomain.domain.TLD.TLD/more/url ,但有时候,它可能只是http://domain.TLD.TLD/more/url (这只是指向www

所以这就是我提出的:

 public static class UriExtensions { private const string TopLevelDomainRegex = @"(\.[^\.]{2,3}|\.[^\.]{2,3}\.[^\.]{2,3})$"; private const string UnspecifiedSubdomainRegex = @"^((http[s]?|ftp):\/\/)(()([^:\/\s]+))(:([^\/]*))?((?:\/)?|(?:\/)(((\w+)*\/)([\w\-\.]+[^#?\s]+)(\?([^#]*))?(#(.*))?))?$"; private const string SpecifiedSubdomainRegex = @"^((http[s]?|ftp):\/\/)(([^.:\/\s]*)[\.]([^:\/\s]+))(:([^\/]*))?((?:\/)?|(?:\/)(((\w+)*\/)([\w\-\.]+[^#?\s]+)(\?([^#]*))?(#(.*))?))?$"; public static string AbsolutePathToSubdomain(this Uri uri, string subdomain) { subdomain = subdomain == "www" ? string.Empty : string.Concat(subdomain, "."); var replacement = "$1{0}$5$6".FormatWith(subdomain); var spec = Regex.Replace(uri.Authority, TopLevelDomainRegex, string.Empty).Distinct().Count(c => c == '.') != 0; return Regex.Replace(uri.AbsoluteUri, spec ? SpecifiedSubdomainRegex : UnspecifiedSubdomainRegex, replacement); } } 

基本上这个代码我采用System.Uri和:

  1. 使用Authority属性获取subdomain.domain.TLD.TLD
  2. 将它与“伪TLD”相匹配(我永远不会有一个2-3字母的注册域会破坏正则表达式,它基本上会检查以.XX[X].XX[X].XX[X]结尾的任何内容。 .XX[X].XX[X]
  3. 我剥离了TLD,最终得到了domainsubdomain.domain domain subdomain.domain
  4. 如果结果数据为零点,我使用UnspecifiedSubdomainRegex ,因为我无法弄清楚如何使用SpecifiedSubdomainRegex告诉它如果它在该部分没有点,它应该返回string.Empty

那么我的问题是,是否有办法将这三个正则表达式合并为更简单的东西

PD:忘了javascript,我只是用它来动态测试正则表达式

您可以使用(?(?=condition)then|else)构造来完成此操作。 但是,这在JavaScript中不可用(但它在.NET,Perl和PCRE中可用):

 ^(?(?=(?:[^.]*\.){3}[^.]*$)aaa|eee) 

例如,将检查一个字符串是否包含正好三个点,如果是,它会尝试匹配字符串开头的aaa ; 否则它会尝试匹配eee 。 所以它将匹配前三个字母

 aaa.bbb.ccc.ddd eee.ddd.ccc.bbb.aaa eee 

但失败了

 aaa.bbb.ccc eee.ddd.ccc.bbb aaa.bbb.ccc.ddd.eee 

说明:

 ^ # Start of string (? # Conditional: If the following lookahead succeeds: (?= # Positive lookahead - can we match... (?: # the following group, consisting of [^.]*\. # 0+ non-dots and 1 dot ){3} # 3 times [^.]* # followed only by non-dots... $ # until end-of-string? ) # End of lookahead aaa # Then try to match aaa | # else... eee # try to match eee ) # End of conditional 
 ^(?:[^.]*\.[^.]*){3}$ 

上面的正则表达式将匹配正好有3个点的字符串— http://rubular.com/r/Tsaemvz1Yi

 ^(?:[^.]*\.[^.]*){4,}$ 

这一个 – 对于有4个点或更多点的字符串— http://rubular.com/r/IJDeQWVhEB

在Python中(对不起;但正则表达式没有语言边界)

 import re regx = re.compile('^([^.]*?\.){3}[^.]*?\.') for ss in ("aaa.bbb.ccc", "aaa.bbb.ccc.ddd", 'aaa.bbb.ccc.ddd.eee', 'abcdefghi..'): if regx.search(ss): print ss + ' has at least 4 dots in it' else: print ss + ' has a maximum of 3 dots in it' 

结果

 aaa.bbb.ccc has a maximum of 3 dots in it aaa.bbb.ccc.ddd has a maximum of 3 dots in it aaa.bbb.ccc.ddd.eee has at least 4 dots in it abcdefghi.. has at least 4 dots in it 

这个正则表达式模式不要求分析整个字符串(其中没有符号$)。 在长弦上更好。

你不需要Regex(和许多其他常见任务一样)。

 public static string AbsolutePathToSubdomain(this Uri uri, string subdomain) { // Pre-process the new subdomain if (subdomain == null || subdomain.Equals("www", StringComparison.CurrentCultureIgnoreCase)) subdomain = string.Empty; // Count number of TLDs (assume at least one) List parts = uri.Host.Split('.').ToList(); int tldCount = 1; if (parts.Count >= 2 && parts[parts.Count - 2].Length <= 3) { tldCount++; } // Drop all subdomains if (parts.Count - tldCount > 1) parts.RemoveRange(0, parts.Count - tldCount - 1); // Add new subdomain, if applicable if (subdomain != string.Empty) parts.Insert(0, subdomain); // Construct the new URI UriBuilder builder = new UriBuilder(uri); builder.Host = string.Join(".", parts.ToArray()); builder.Path = "/"; builder.Query = ""; builder.Fragment = ""; return builder.Uri.ToString(); }