.NET RegEx用于替换URL中的语言代码

时间:2018-07-23 10:21:15

标签: c# .net regex

如何在C#函数中更改以下正则表达式以获取如下所示的结果?因为语言代码的总数是固定的,我可以只修改RegEx模式而不是C#代码吗?谢谢。

C#函数:

public static string GetSubdomain(string url)
{
    string pat = @"^https://www\.(.*?)/(english|german|italian)/.*$";
    string rep = @"http://$2.$1/";
    return Regex.Replace(url, pat, rep);
}

结果:

http://www.example.org/english/  => http://en.example.org/
http://www.example.org/german/   => http://de.example.org/
http://www.example.org/italian/  => http://it.example.org/

3 个答案:

答案 0 :(得分:2)

您可以使用语言名称和代码的词典,并使用以下解决方案:

var dct = new Dictionary<string, string>(StringComparer.OrdinalIgnoreCase) {
    { "english", "en"},
    { "german", "de"},
    { "italian", "it" }
};
//var url = "http://www.example.org/english/"; // http://en.example.org/
var url = "https://www.example.org/german/"; // https://de.example.org/
string pat = @"(?i)^(https?://)www\.(.*?)/(english|german|italian)/.*$";
Console.WriteLine(Regex.Replace(url, pat, m => {
        var val = "";   
        return dct.TryGetValue(m.Groups[3].Value, out val) ?
          $"{m.Groups[1].Value}{dct[m.Groups[3].Value]}.{m.Groups[2].Value}/" :
          $"{m.Groups[1].Value}{m.Groups[3].Value}.{m.Groups[2].Value}/";
      }
    )
);

请参见C# demo

模式匹配

  • (?i)-使正则表达式不区分大小写
  • ^-字符串的开头
  • (https?://)-第1组:http://https://
  • www\.-一个www.(用(?:...)?包装以进行可选匹配)
  • (.*?)-第2组:任意0个以上的字符,数量尽可能少
  • /-一个/
  • (english|german|italian)-第3组:3种选择中的任意一种
  • /-一个/
  • .*-该行的其余部分
  • $-字符串的结尾。

匹配后,dct.TryGetValue(m.Groups[3].Value, out val) ?检查是否可以将第3组值映射到语言代码,如果是,则使用dct[m.Groups[3].Value]进行替换。否则,m.Groups[3].Value照常使用。

答案 1 :(得分:1)

您将需要一张地图,从中可以得出正则表达式。

private static readonly Dictionary<string, string> LangMap = new Dictionary<string, string>
{
    { "english", "en" },
    { "german", "de" },
    { "italian", "it" }
};

private static readonly string LangString = string.Join("|", LangMap.Keys.Select(x => x).ToArray());
private static readonly Regex LangPattern = new Regex($@"(?<=https://www\.(.*?)/)({LangString})(?=/.*$)");

public static string GetSubdomain(string url)
{
    var match = LangPattern.Match(url);
    return $"http://{LangMap[match.Groups[2].Value]}.{match.Groups[1].Value}/";
}

答案 2 :(得分:0)

一般情况下,我怀疑正则表达式是否有用?我们应该首先检测文化(假设您坚持 ISO 3166 ):

private static CultureInfo CultureFormAddress(string address) {
  if (string.IsNullOrWhiteSpace(address))
    return CultureInfo.InvariantCulture;

  Uri uri = new Uri(address);
  var cultures = CultureInfo.GetCultures(CultureTypes.NeutralCultures);

  foreach (string segment in uri.Segments) {
    CultureInfo result = cultures
      .FirstOrDefault(culture => string.Equals(culture.EnglishName,
         segment.Trim('/'), 
         StringComparison.OrdinalIgnoreCase));

    if (result != null)
      return result;
  }

  return CultureInfo.InvariantCulture;
}

然后才转换uri:

public static string GetSubdomain(string address) {
  CultureInfo culture = CultureFormAddress(address);

  if (culture == CultureInfo.InvariantCulture)
    return address;

  Uri uri = new Uri(address);

  return string.Concat(
    $"{uri.Scheme}://{culture.Name}.",
      uri.Host.StartsWith("www.", StringComparison.OrdinalIgnoreCase) 
        ? uri.Host.Substring("www.".Length) 
        : uri.Host,
      "/",
      string.Join("/", uri.LocalPath
        .Split('/')
        .SkipWhile(item => string.IsNullOrEmpty(item))
        .Skip(1))
      );
} 

例如(让我们提供一种“未知”文化-俄语和方案-Ftp。让我们添加本地路径-“ bla-bla-bla”):

// ftp://ru.example.org/bla-bla-bla
GetSubdomain("ftp://www.example.org/russian/bla-bla-bla");

其他测试:

  string[] tests = new string[] {
    "http://www.example.org/english/",
    "http://www.example.org/german/",
    "http://www.example.org/italian/" };

  Console.Write(string.Join(Environment.NewLine, tests
    .Select(test => $"{test,-35} => {GetSubdomain(test)}")));

结果:

http://www.example.org/english/     => http://en.example.org/
http://www.example.org/german/      => http://de.example.org/
http://www.example.org/italian/     => http://it.example.org/