2015-06-05 151 views
8

我想将camelCasePascalCase单词分隔为单独的单词集合。忽略现有空格将CamelCase转换为空格字符串

到目前为止,我有:

Regex.Replace(value, @"(\B[A-Z]+?(?=[A-Z][^A-Z])|\B[A-Z]+?(?=[^A-Z]))", " $0", RegexOptions.Compiled); 

它工作正常的转换“TestWord”到“测试字”和离开单个词不变,例如Testing仍为Testing

但是,ABCTest得到转换为A B C Test时,我更喜欢ABC Test

回答

4

尝试:

[A-Z][a-z]+|[A-Z]+(?=[A-Z][a-z])|[a-z]+|[A-Z]+ 

An example on Regex101


它是如何在CS中使用?

string strText = " TestWord asdfDasdf ABCDef"; 

string[] matches = Regex.Matches(strText, @"[A-Z][a-z]+|[A-Z]+(?=[A-Z][a-z])|[a-z]+|[A-Z]+") 
       .Cast<Match>() 
       .Select(m => m.Value) 
       .ToArray(); 

string result = String.Join(" ", matches); 

result = 'Test Word asdf Dasdf ABC Def'


它是如何工作

在这个例子中的字符串:

TestWord qwerDasdf 
ABCTest Testing ((*&^%$CamelCase!"£$%^^)) 
asdfAasdf 
AaBbbCD 

[A-Z][a-z]+比赛:

  • [0-4] Test
  • [4-8] Word
  • [13-18] Dasdf
  • [22-26] Test
  • [27-34] Testing
  • [45 -50] Camel
  • [50-54] Case
  • [68-73] Aasdf
  • [74-76] Aa
  • [76-79] Bbb

[A-Z]+(?=[A-Z][a-z])匹配:

  • [19-22] ABC

[a-z]+匹配:

  • [9-13] qwer
  • [64-68] asdf

[A-Z]+比赛:

  • [79-81] CD
+0

感谢你的回复,但是当这个值已经有一个空格的时候它不起作用。它最终使空间加倍,即“ABC测试”变成“ABC测试”,同样“ABCTest”变成“ABC测试”,即保持前导空间。 –

+1

@CiaranMartin我会使用'Regex.match()'获得上面列出的所有匹配的MatchCollection。然后,您可以将其转换为数组,并使用单个空格分隔符将其加入到字符串中。这使得你的正则表达式保留了很多逻辑并使代码更具可读性。 – thodic

+0

@CiaranMartin请参阅我对C#实现的编辑。 – thodic

1

这里是我的尝试:

(?<!^|\b|\p{Lu})\p{Lu}+(?=\p{Ll}|\b)|(?<!^\p{Lu}*|\b)\p{Lu}(?=\p{Ll}|(?<!\p{Lu}*)\b) 

该正则表达式可与Regex.Replace$0一起用作替换字符串。

Regex.Replace(value, @"(?<!^|\b|\p{Lu})\p{Lu}+(?=\p{Ll}|\b)|(?<!^\p{Lu}*|\b)\p{Lu}(?=\p{Ll}|(?<!\p{Lu}*)\b)", " $0", RegexOptions.Compiled); 

demo

正则表达式说明:

  • 包含2层的替代品,以考虑之前或之后小写字母大写字母链。
  • (?<!^|\b|\p{Lu})\p{Lu}+(?=\p{Ll}|\b) - 匹配未被前面有串字边界或其他大写字母的开始,而之后是小写字母或单词边界几个大写字母第一替代方案,
  • (?<!^\p{Lu}*|\b)\p{Lu}(?=\p{Ll}|(?<!\p{Lu}*)\b) - 第二个选择匹配单个大写字母,该大写字母前面没有以紧跟可选大写字母的字符串开头,或者字边界,后面跟着小写字母或没有可选大写字母的单词边界。
+0

你有没有时间检查我的方法? –

+0

我做到了,但RegEx很难解释\ p {Lu}语法。我已经测试过它,它在“ABC测试”中没有正确工作,因为它在我预期的时候输出“AB C测试”“ABC测试” –

+0

但事实并非如此,请仔细看看RegexStorm演示中的上下文选项卡。它显示'ABC测试'。 '\ p {Lu}'是一个大写字母,'\ p {Ll}'是一个小写字母,*它支持Unicode *。它将与俄文或波兰文以及其他大写/小写的脚本一起工作。 –

0

您是否有使用Regex的要求?说实话,我根本不会使用Regex。它们很难调试,并且不易读取。

我会用一个小的,可重复使用,易于测试的扩展方法去:

class Program 
{ 
    static void Main(string[] args) 
    { 
     string[] inputs = new[] 
     { 
      "ABCTest", 
      "HelloWorld", 
      "testTest$Test", 
      "aaҚbb" 
     }; 

     var output = inputs.Select(x => x.SplitWithSpaces(CultureInfo.CurrentUICulture)); 

     foreach (string x in output) 
     { 
      Console.WriteLine(x); 
     } 

     Console.Read(); 
    } 
} 

public static class StringExtensions 
{ 
    public static bool IsLowerCase(this TextInfo textInfo, char input) 
    { 
     return textInfo.ToLower(input) == input; 
    } 

    public static string SplitWithSpaces(this string input, CultureInfo culture = null) 
    { 
     if (culture == null) 
     { 
      culture = CultureInfo.InvariantCulture; 
     } 
     TextInfo textInfo = culture.TextInfo; 

     StringBuilder sb = new StringBuilder(input); 

     for (int i = 1; i < sb.Length; i++) 
     { 
      int previous = i - 1; 

      if (textInfo.IsLowerCase(sb[previous])) 
      { 
       int insertLocation = previous - 1; 

       if (insertLocation > 0) 
       { 
        sb.Insert(insertLocation, ' '); 
       } 

       while (i < sb.Length && textInfo.IsLowerCase(sb[i])) 
       { 
        i++; 
       } 
      }     
     } 

     return sb.ToString(); 
    } 
} 
+0

感谢您的回答,但我不需要处理文化差异,并感觉OhAuth的答案更直接,更简洁,即使它有正则表达式,在最好的时候也不是最容易理解的! –

相关问题