如何在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/
答案 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/