【问题标题】:Transform title into dashed URL-friendly string [closed]将标题转换为 URL 友好的虚线字符串 [关闭]
【发布时间】:2011-01-10 19:49:56
【问题描述】:

我想编写一个 C# 方法,将任何标题转换为 URL 友好字符串,类似于 Stack Overflow 所做的:

  • 用破折号替换空格
  • 去掉括号

我正在考虑根据 RFC 3986 标准(来自 Wikipedia)删除保留字符,但我不知道这是否足够?它会使链接可用,但有谁知道在stackoverflow这里替换了哪些其他字符?我不想在我的网址中以 %-s 结尾...

当前实现

string result = Regex.Replace(value.Trim(), @"[!*'""`();:@&+=$,/\\?%#\[\]<>«»{}_]");
return Regex.Replace(result.Trim(), @"[\s*[\-–—\s]\s*]", "-");

我的问题

  1. 我应该删除哪些字符?
  2. 我应该限制结果字符串的最大长度吗?
  3. 有人知道 SO 上的标题适用哪些规则吗?

【问题讨论】:

  • 如果您可以发布单独的问题而不是将您的问题合并为一个问题,则最好。这样,它可以帮助回答您的问题的人以及其他寻找您的至少一个问题的人。

标签: c# replace


【解决方案1】:

大多数“sluggifiers”(转换为友好 url 类型名称的方法)倾向于执行以下操作:

  1. 去除除空格、破折号、下划线和字母数字以外的所有内容。
  2. (可选)删除“常用词”(the、a、an、of 等)。
  3. 用破折号替换空格和下划线。
  4. (可选)转换为小写。

据我所知,StackOverflow 的 sluggifier 执行 #1、#3 和 #4,但不是 #2。

【讨论】:

  • 所以我的替换是相同的:1、3 和 4。我只需要在第一个 reg ex 模式中添加下划线。
【解决方案2】:

我会做的:

string url = title;
url = Regex.Replace(url, @"^\W+|\W+$", "");
url = Regex.Replace(url, @"'\"", "");
url = Regex.Replace(url, @"_", "-");
url = Regex.Replace(url, @"\W+", "-");

基本上这是在做什么:

  • 去除标题开头和结尾的非单词字符;
  • 去掉单引号和双引号(主要是去掉单词中间的撇号);
  • 用连字符替换下划线(下划线在技术上是一个单词字符以及数字和字母);和
  • 用一个连字符替换所有非单词字符组。

【讨论】:

  • 我想知道为什么这没有得到更多的选票?非常简单易懂且解释清楚。我还想知道 String.Replace 对于步骤 2 和 3 是否会更快,它们是文字字符替换,但实际上并不存在。我也对 ^\W 非单词字符如何使用 unicode 和非拉丁语言感兴趣?如果它处理那些稍微好一点,我会说这是最好的答案。最后的建议 - 我确实喜欢之前用 'and' 替换 '&' 的建议。
  • 哦 - 最后一件事,我认为在第三行(第二个 .Replace)中,@"'\"" 实际上应该是 @"'"""
【解决方案3】:

而不是寻找要替换的东西,unreserved chars is so short 的列表,它将成为一个很好的清晰正则表达式。

return Regex.Replace(value, @"[^A-Za-z0-9_\.~]+", "-");

(请注意,我没有在允许的字符列表中包含破折号;所以它被“1 个或多个”运算符 [+] 吞噬,因此多个破折号(在原始的或生成的或根据多米尼克·罗杰(Dominic Rodger)的出色观点,组合)崩溃了。)

您可能还想删除常用词(“the”、“an”、“a”等),尽管这样做会稍微改变句子的含义。可能还想删除任何尾随的破折号和句点。

还强烈建议您做 SO 和其他人所做的事情,并包含一个唯一标识符other,而不是标题,然后在处理 URL 时只使用该唯一 ID。所以http://example.com/articles/1234567/is-the-pop-catholic(注意缺少的'e')和http://example.com/articles/1234567/is-the-pope-catholic解析到同一个资源。

【讨论】:

  • 然而,白名单方法确实会阻止 Unicode 字符(在 IRI 中)通过。
  • @Bobince:没错。我还必须提供我们的语言相关字符(来自东欧字符集)
  • @Robert:IRI (RFC3987; ietf.org/rfc/rfc3987.txt) 改变了游戏规则。如果它很重要,您可能想在问题中提及它。将支持的 IRI 值添加到白名单似乎并不难。对于强相似性,您可能需要对其进行预过滤。
  • @TJCrowder:不应该。 (点)在你的正则表达式模式中被转义?
  • @Robert:我不认为这样,但坦率地说,我不确定并且必须检查。这样做是无害的,我已经相应地编辑了答案。点(此处的任何字符)的通常含义在字符类构造中没有任何意义。您必须转义 `(显然)、-(因为它在构造中创建一个范围)和 ](关闭它),但我不认为你有逃避大多数其他人。
【解决方案4】:

这个怎么样:

string FriendlyURLTitle(string pTitle)
{
    pTitle = pTitle.Replace(" ", "-");
    pTitle = HttpUtility.UrlEncode(pTitle);
    return Regex.Replace(pTitle, "\%[0-9A-Fa-f]{2}", "");
}

【讨论】:

    【解决方案5】:

    这就是我目前的表达方式。

            public static string Slug(this string value)
        {
            if (value.HasValue())
            {
                var builder = new StringBuilder();
                var slug = value.Trim().ToLowerInvariant();
    
                foreach (var c in slug)
                {
                    switch (c)
                    {
                        case ' ':
                            builder.Append("-");
                            break;
                        case '&':
                            builder.Append("and");
                            break;
                        default:
    
                            if ((c >= '0' && c <= '9') || (c >= 'a' && c <= 'z') && c != '-')
                            {
                                builder.Append(c);
                            }
    
                            break;
                    }
                }
    
                return builder.ToString();
            }
    
            return string.Empty;
        }
    

    【讨论】:

    • 对不起,我宁愿使用正则表达式。您的多行代码最多可以很容易地被两个正则表达式替换。
    • 是的,但是当正则表达式非常复杂且难以理解时,您会付出什么代价。我宁愿拥有可维护性,而不是 2 个神秘的正则表达式 :)
    【解决方案6】:

    我用这个...

        public static string ToUrlFriendlyString(this string value)
        {
            value = (value ?? "").Trim().ToLower();
    
            var url = new StringBuilder();
    
            foreach (char ch in value)
            {
                switch (ch)
                {
                    case ' ':
                        url.Append('-');
                        break;
                    default:
                        url.Append(Regex.Replace(ch.ToString(), @"[^A-Za-z0-9'()\*\\+_~\:\/\?\-\.,;=#\[\]@!$&]", ""));
                        break;
                }
            }
    
            return url.ToString();
        }
    

    【讨论】:

      【解决方案7】:

      这对我有用

      string output = Uri.UnescapeDataString(input);
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2014-06-25
        • 1970-01-01
        • 1970-01-01
        • 2016-04-29
        • 2023-03-06
        相关资源
        最近更新 更多