2015-06-05 198 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的答案更直接,更簡潔,即使它有正則表達式,在最好的時候也不是最容易理解的! –

相關問題