我需要解析一些数据,我想转换
AutomaticTrackingSystem
到
Automatic Tracking System
基本上在任何大写字母之前放置一个空格(当然除了第一个之外)
答案 0 :(得分:26)
您可以使用外观,例如:
string[] tests = {
"AutomaticTrackingSystem",
"XMLEditor",
};
Regex r = new Regex(@"(?!^)(?=[A-Z])");
foreach (string test in tests) {
Console.WriteLine(r.Replace(test, " "));
}
Automatic Tracking System
X M L Editor
正则表达式(?!^)(?=[A-Z])
由两个断言组成:
(?!^)
- 即我们不在字符串的开头(?=[A-Z])
- 即我们就在大写字母之前(?<=#)[^#]+(?=#)
work? 当你有几个不同的规则,和/或你想Split
而不是Replace
时,使用断言确实有所作为。这个例子结合了两个:
string[] tests = {
"AutomaticTrackingSystem",
"XMLEditor",
"AnXMLAndXSLT2.0Tool",
};
Regex r = new Regex(
@" (?<=[A-Z])(?=[A-Z][a-z]) # UC before me, UC lc after me
| (?<=[^A-Z])(?=[A-Z]) # Not UC before me, UC after me
| (?<=[A-Za-z])(?=[^A-Za-z]) # Letter before me, non letter after me
",
RegexOptions.IgnorePatternWhitespace
);
foreach (string test in tests) {
foreach (string part in r.Split(test)) {
Console.Write("[" + part + "]");
}
Console.WriteLine();
}
[Automatic][Tracking][System]
[XML][Editor]
[An][XML][And][XSLT][2.0][Tool]
答案 1 :(得分:19)
如果没有正则表达式,你可以做类似的事情(或者使用LINQ更简洁的事情):
(注意:没有错误检查,你应该添加它)
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace SO
{
class Program
{
static void Main(string[] args)
{
String test = "AStringInCamelCase";
StringBuilder sb = new StringBuilder();
foreach (char c in test)
{
if (Char.IsUpper(c))
{
sb.Append(" ");
}
sb.Append(c);
}
if (test != null && test.Length > 0 && Char.IsUpper(test[0]))
{
sb.Remove(0, 1);
}
String result = sb.ToString();
Console.WriteLine(result);
}
}
}
这给出了输出
A String In Camel Case
答案 2 :(得分:4)
我刚刚写了一个函数来完成这个。 :)
将([a-z])([A-Z])
替换为$1 $2
(或其他语言中的\1 \2
)。
我也替换了([A-Z]+)([A-Z][a-z])
- 这会将“NumberOfABCDThings”等内容转换为“ABCD事物数量”
所以在C#中,这看起来像是:
Regex r1 = new Regex(@"([a-z])([A-Z])");
Regex r2 = new Regex(@"([A-Z]+)([A-Z][a-z])");
NewString = r1.Replace( InputString , "$1 $2");
NewString = r2.Replace( NewString , "$1 $2");
(虽然可能有更复杂的写作方式)
如果您可能有标点符号或数字,我猜您可以尝试([^A-Z])([A-Z])
进行第一场比赛
嗯,使用lookbehind和lookahead编写这些正则表达式的另一种方法是匹配位置并插入一个空格 - 即(?<=[a-z])(?=[A-Z])
和(?<=[A-Z]+)(?=[A-Z][a-z])
,并且在两种情况下都只替换为“” - 不确定该方法是否有优势,但这是一种有趣的方式。 :)
答案 3 :(得分:3)
显然,反向正则表达式有一个选项:-)我们现在可以消除字符串反转,这是另一种方法:
using System;
using System.Linq;
using System.Text.RegularExpressions;
class MainClass
{
public static void Main (string[] args)
{
Regex ry = new Regex
(@"([A-Z][a-z]+|[A-Z]+[A-Z]|[A-Z]|[^A-Za-z]+[^A-Za-z])",
RegexOptions.RightToLeft);
string[] tests = {
"AutomaticTrackingSystem",
"XMLEditor",
"AnXMLAndXSLT2.0Tool",
"NumberOfABCDThings",
"AGoodMan",
"CodeOfAGoodMan"
};
foreach(string t in tests)
{
Console.WriteLine("\n\n{0} -- {1}", t, ry.Replace(t, " $1"));
}
}
}
输出:
AutomaticTrackingSystem -- Automatic Tracking System
XMLEditor -- XML Editor
AnXMLAndXSLT2.0Tool -- An XML And XSLT 2.0 Tool
NumberOfABCDThings -- Number Of ABCD Things
AGoodMan -- A Good Man
CodeOfAGoodMan -- Code Of A Good Man
答案 4 :(得分:0)
如果您试图保持首字母缩略词的完整性,请将“([^ A-Z])([A-Z])”替换为“\ 1 \ 2”, 否则将“(。)([A-Z])”改为“\ 1 \ 2”。
答案 5 :(得分:0)
试试这个:
using System;
using System.Linq;
using System.Text.RegularExpressions;
class MainClass
{
public static void Main (string[] args)
{
var rx = new Regex
(@"([a-z]+[A-Z]|[A-Z][A-Z]+|[A-Z]|[^A-Za-z][^A-Za-z]+)");
string[] tests = {
"AutomaticTrackingSystem",
"XMLEditor",
"AnXMLAndXSLT2.0Tool",
"NumberOfABCDThings",
"AGoodMan",
"CodeOfAGoodMan"
};
foreach(string t in tests)
{
string y = Reverse(t);
string x = Reverse( rx.Replace(y, @" $1") );
Console.WriteLine("\n\n{0} -- {1}",y,x);
}
}
static string Reverse(string s)
{
var ca = s.ToCharArray();
Array.Reverse(ca);
string t = new string(ca);
return t;
}
}
输出:
metsySgnikcarTcitamotuA -- Automatic Tracking System
rotidELMX -- XML Editor
looT0.2TLSXdnALMXnA -- An XML And XSLT 2.0 Tool
sgnihTDCBAfOrebmuN -- Number Of ABCD Things
naMdooGA -- A Good Man
naMdooGAfOedoC -- Code Of A Good Man
它的工作原理是向后扫描字符串,并使大写字母成为终结符。希望RegEx有一个参数可以向后扫描字符串,因此不再需要上面单独的字符串反转: - )
答案 6 :(得分:0)
只需使用这个linq one-liner :(完全适合我)
public static string SpaceCamelCase(string input)
{
return input.Aggregate(string.Empty, (old, x) => $"{old}{(char.IsUpper(x) ? " " : "")}{x}").TrimStart(' ');
}