如何有条件的正则表达式

时间:2011-07-24 02:26:01

标签: c# regex

我想要一个正则表达式,如果它在字符串中有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. 使用subdomain.domain.TLD.TLD属性{/ 1}}。
  2. 将其与“伪TLD”相匹配(我永远不会有一个注册域名,其中2-3个字母会破坏正则表达式,这基本上会检查以Authority.XX[X]结尾的任何内容)
  3. 我剥离顶级域名,最终得到.XX[X].XX[X]domain
  4. 如果结果数据为零点,我使用subdomain.domain,因为我无法弄清楚如何使用UnspecifiedSubdomainRegex告诉它如果该部分没有点,它应该返回SpecifiedSubdomainRegex
  5. 我的问题是,是否有办法将这三个正则表达成合并为更简单的

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

4 个答案:

答案 0 :(得分:14)

您可以使用(?(?=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

答案 1 :(得分:1)

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

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

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

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

答案 2 :(得分:1)

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

import re

regx = re.compile('^([^.]*?\.){3}[^.]*?\.')

for ss in ("aaa.bbb.ccc",
           "aaa.bbb.ccc.ddd",
           'aaa.bbb.ccc.ddd.eee',
           'a.b.c.d.e.f.g.h.i...'):
  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
a.b.c.d.e.f.g.h.i...     has at least 4 dots in it

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

答案 3 :(得分:0)

你不需要正则表达式(和许多其他常见任务一样)。

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<string> 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();
}