2012-03-12 45 views
0

我有以下方法时(而且看上去过于昂贵),用于创建永久链接,但它缺少一些东西,是不错的永久链接很重要:使用正则表达式或字符串操作创建永久链接

public string createPermalink(string text) 
     { 
      text = text.ToLower().TrimStart().TrimEnd(); 

      foreach (char c in text.ToCharArray()) 
      { 
       if (!char.IsLetterOrDigit(c) && !char.IsWhiteSpace(c)) 
       { 

        text = text.Replace(c.ToString(), ""); 
       } 

       if (char.IsWhiteSpace(c)) 
       { 
        text = text.Replace(c, '-'); 
       } 
      } 

      if (text.Length > 200) 
      { 
       text = text.Remove(200); 
      } 

      return text; 
     } 

很少的东西,缺乏它:

如果有人输入文字是这样的: "My choiches are:foo,bar"会得到返回"my-choices-arefoobar" ,它应该是这样的:"my-choiches-are-foo-bar"

和如果有人输入多个空格,它将返回为“---”,这在URL中不好。

有一些更好的方式在正则表达式来做到这一点(我真的只用它几次)?


UPDATE:

要求是:在开头或结尾

  • 任何非数字或字母字符不允许
  • 任何非数字或字母字符应该“替换 - “
  • 替换为” - “字符不应该像”---“一样重复
  • 最后是strippi ng字符串索引200以确保它不会太长

回答

2

更改为

public string createPermalink(string text) 
{ 
    text = text.ToLower(); 

    StringBuilder sb = new StringBuilder(text.Length); 

    // We want to skip the first hyphenable characters and go to the "meat" of the string 
    bool lastHyphen = true; 

    // You can enumerate directly a string 
    foreach (char c in text) 
    { 
     if (char.IsLetterOrDigit(c)) 
     { 
      sb.Append(c); 
      lastHyphen = false; 
     }  
     else if (!lastHyphen) 
     { 
      // We use lastHyphen to not put two hyphens consecutively 
      sb.Append('-'); 
      lastHyphen = true; 
     } 

     if (sb.Length == 200) 
     { 
      break; 
     } 
    } 

    // Remove the last hyphen 
    if (sb.Length > 0 && sb[sb.Length - 1] == '-') 
    { 
     sb.Length--; 
    } 

    return sb.ToString(); 
} 

如果你真的想使用正则表达式,你可以做这样的事情(基于贾斯汀的代码)

Regex rgx = new Regex(@"^\W+|\W+$");  
Regex rgx2 = new Regex(@"\W+"); 
return rgx2.Replace(rgx.Replace(text.ToLower(), string.Empty), "-"); 
对于非单词字符开头

第一正则表达式搜索(1或更大)(^)或在字符串($)和删除它们的端部。第二个替换一个或多个非单词字符-

+0

就是这样,只有缺少的东西是,如果第一个字符是以“ - ”开头,但我可以为自己添加检查。 – formatc 2012-03-12 14:41:03

+0

更正...现在它检查。 – xanatos 2012-03-12 14:42:28

+0

谢谢,我会看到更快速地使用它! – formatc 2012-03-12 14:46:27

1

这应该可以解决您已解释的问题。请让我知道是否需要进一步解释。 正如一个供参考,正则表达式让得到它在一个运行

//This will find any non-character word, lumping them in one group if more than 1 
//It will ignore non-character words at the beginning or end of the string 
Regex rgx = new Regex(@"(?!\W+$)\W+(?<!^\W+)"); 
//This will then replace those matches with a - 
string result = rgx.Replace(input, "-"); 

进行使用lookarounds为了保持字符串从超越200个字符,你将不得不使用substring。如果你正则表达式之前做到这一点,那么你会没事的,但如果你以后做,然后你再运行具有后划线的风险,仅供参考。

例如:

myString.Substring(0,200) 
+0

问题也是如果字符串结尾像“你好!”的标志。会被翻译成“hello-”,这对于URL的结束并不好。 – formatc 2012-03-12 14:32:56

+0

更新我的代码来处理最后的 - 。请确保更新您的问题以反映此新需求,但 – 2012-03-12 14:46:25

+0

重新更新我的代码以处理您的新需求。我能够使这成为一个正则表达式:) – 2012-03-12 15:27:30

0

我使用迭代方法这个 - 因为在某些情况下,您可能希望某些字符变成单词而不是让它们化作“ - ”字符 - 例如'&' - >'和'。

但是,当你做到了,也最终会与可能包含多个字符串“ - ” - 所以你有折叠所有多最后的正则表达式“ - ”字符转换成一个。

所以我会建议使用正则表达式的有序列表,然后运行他们都在秩序。此代码被写入静态类,然后作为System.String的单个扩展方法公开 - 并且可能最好合并到System名称空间中。

我从我使用的具有可扩展性的代码入侵了它(例如,您可以通过MatchEvaluator构建更换智能替换对象的替换对象;您可以传入自己的IEnumerable替换项,如类是公开的),因此它可能看起来不必要的复杂 - 根据我猜测每个人都会这样想的其他答案来判断(但我对创建的字符串的搜索引擎优化有特定的要求)。

更换的名单我使用的可能不是您的用途完全正确的 - 如果没有,你可以添加更多。

private class SEOSymbolReplacement 
{ 
    private Regex _rx; 
    private string _replacementString; 

    public SEOSymbolReplacement(Regex r, string replacement) 
    { 
    //null-checks required. 
    _rx = r; 
    _replacementString = replacement; 
    } 

    public string Execute(string input) 
    { 
    /null-check required 
    return _rx.Replace(input, _replacementString); 
    } 
} 

private static readonly SEOSymbolReplacement[] Replacements = { 
    new SEOSymbolReplacement(new Regex(@"#", RegexOptions.Compiled), "Sharp"), 
    new SEOSymbolReplacement(new Regex(@"\+", RegexOptions.Compiled), "Plus"), 
    new SEOSymbolReplacement(new Regex(@"&", RegexOptions.Compiled), " And "), 
    new SEOSymbolReplacement(new Regex(@"[|:'\\/,_]", RegexOptions.Compiled), "-"), 
    new SEOSymbolReplacement(new Regex(@"\s+", RegexOptions.Compiled), "-"), 
    new SEOSymbolReplacement(new Regex(@"[^\p{L}\d-]", 
          RegexOptions.IgnoreCase | RegexOptions.Compiled), ""), 
    new SEOSymbolReplacement(new Regex(@"-{2,}", RegexOptions.Compiled), "-")}; 


/// <summary> 
/// Transforms the string into an SEO-friendly string. 
/// </summary> 
/// <param name="str"></param> 
public static string ToSEOPathString(this string str) 
{ 
    if (str == null) 
     return null; 
    string toReturn = str; 
    foreach (var replacement in DefaultReplacements) 
    { 
     toReturn = replacement.Execute(toReturn); 
    } 
    return toReturn; 
} 
+0

这是很好的altought我认为,“#”的翻译最好是“数字”,而不是“尖锐”,至少在应用程序中,你不希望人们写“C#”之类的东西。 – formatc 2012-03-12 15:07:15

+0

是的,你是对的。我们使用它作为'“Sharp”'特别是因为可能性最初的短语是''C#''''''F# – 2012-03-12 15:08:48