C# 我可以使用相同的子字符串作为不同捕获的一部分吗?

C# 我可以使用相同的子字符串作为不同捕获的一部分吗?,c#,regex,C#,Regex,我想创建一个函数,允许我将CamelCase转换为Title Case。对于正则表达式来说,这似乎是一项很好的任务,但如果您有更好的解决方案,我不会致力于使用正则表达式 这是我的第一次尝试,在大多数情况下都有效,但我将在几行文字中讨论一些问题: private static Regex camelSplitRegex = new Regex(@"(\S)([A-Z])"); private static String camelReplacement = "$1 $2"; public Str

我想创建一个函数,允许我将CamelCase转换为Title Case。对于正则表达式来说,这似乎是一项很好的任务,但如果您有更好的解决方案,我不会致力于使用正则表达式

这是我的第一次尝试,在大多数情况下都有效,但我将在几行文字中讨论一些问题:

private static Regex camelSplitRegex = new Regex(@"(\S)([A-Z])");
private static String camelReplacement = "$1 $2";

public String SplitCamel(String text){
    return camelSplitRegex.Replace(text, camelReplacement);
}
正则表达式模式查找非空白字符(第一次捕获),后跟大写字母(第二次捕获)。在函数中,
Regex.Replace
用于在第一次和第二次捕获之间插入空格

这适用于许多示例:

  • SplitCamel(“privateField”)
    返回
    “private Field”
  • SplitCamel(“PublicMethod”)
    返回
    “PublicMethod”
  • SplitCamel(“LeadingSpace”)
    根据需要返回
    “前导空格”
    ,而不在“前导”之前插入额外空格
我遇到的问题是在处理多个连续的大写字母时

  • SplitCamel(“NASA”)
    返回“N为”而不是“N为”
  • SplitCamel(“C3PO”)
    返回“C3PO”而不是“C3PO”
  • SplitCamel(“CAPS LOCK FEVER”)
    返回“C AP S L OC K F EVE R”而不是“C A P S L O C K F E V R”
在这些情况下,我认为问题在于每个大写字母只能被捕获为
\S
[A-Z]
,但不能在一次匹配中捕获为
\S
,在下一次匹配中捕获为
[A-Z]



我的主要问题是,.NET正则表达式引擎是否有某种方法支持在连续匹配中作为不同捕获使用的相同子字符串?其次,是否有更好的方法拆分驼峰大小写?

这里有一种非正则表达式方法

public static string SplitCamel(this string stuff)
{
    var builder = new StringBuilder();
    char? prev = null;
    foreach (char c in stuff)
    {
        if (prev.HasValue && !char.IsWhiteSpace(prev.Value) && 'A' <= c && c <= 'Z') 
            builder.Append(' ');
        builder.Append(c);
        prev = c;
    }

    return builder.ToString();
}
印刷品

“私人领域”

“公共方法”

“领先空间”

“A是A”

“C3 p O”

“C A p S L O C K F E V E R”


这里有一个非正则表达式的方法

public static string SplitCamel(this string stuff)
{
    var builder = new StringBuilder();
    char? prev = null;
    foreach (char c in stuff)
    {
        if (prev.HasValue && !char.IsWhiteSpace(prev.Value) && 'A' <= c && c <= 'Z') 
            builder.Append(' ');
        builder.Append(c);
        prev = c;
    }

    return builder.ToString();
}
印刷品

“私人领域”

“公共方法”

“领先空间”

“A是A”

“C3 p O”

“C A p S L O C K F E V E R”


<代码>私有静态正则表达式CAMELSEPTIGEXEX =新正则表达式(@)(?<代码>私有静态正则表达式CAMELSPLITEGEXEX =新正则表达式(@)(?< P>请考虑切换到值类型字符串而不是字符串类)。更新到这个。

 private static Regex camelSplitRegex = new Regex(@"(^\S)?([A-Z])");

请考虑切换到值类型字符串而不是String类。更新到这个。

 private static Regex camelSplitRegex = new Regex(@"(^\S)?([A-Z])");

为了澄清,您确实希望连续的大写字母仍被拆分(即,“NASA”应转到“N A S A”),或者是否有将大写字母块保留为一个块的偏好?结果不应包含两个相互接触的大写字母。为了澄清,您确实希望连续的大写字母仍被拆分(即,“NASA”应改为“N A S A”)或者,是否有一个偏好将一块大写字母保持为一块?结果永远不应该包含两个动人的大写字母。非常简单。我总是忽略向前看和向后看。谢谢。非常简单。我总是忽略向前看和向后看。谢谢。谢谢你提供了非正则表达式的替代方案,但我要去go使用Casimir的前向/后向解决方案。感谢您提供了非正则表达式的替代方案,但我将使用Casimir的前向/后向解决方案。我不确定您的评论的确切含义,我认为您的正则表达式模式在这种情况下不起作用。前面的非空白字符不应是可选的,这将允许进行匹配前面有一个大写字母。关于字符串。请根据您的示例进行测试或提供一个不起作用的示例。请用具体的示例证明它不起作用。虽然我知道由于某种原因它违反Microsoft样式指南,但我通常使用CLR基元类型名称“string”或“Int32”而不是“string”或“int”因此,1)我的所有类型名称在源代码中的颜色相同,2)我的变量声明中使用的类型名称与调用这些类型的静态方法时必须使用的类型名称相匹配(“Int32.Parse(text)”,3)我可以在处理多个.NET语言时使用相同的基元类型名称,以及4)对于“int”或“long”的大小没有任何混淆,这在不同的非.NET语言中是不同的。我想不出使用C#基元类型关键字有什么好处,除了约定和一些需要C#关键字的领域外,比如VS2015之前的枚举类型声明(“Enum MyEnum:byte{}”).我实际上是从《CLR通过C#》一书中得到这个想法的Jeffrey Richter所著。他之所以选择CLR类型名称还有其他一些原因。请查看本PDF第117页第5章的开头。我不确定您的评论的确切含义,我认为您的正则表达式模式在这种情况下不起作用。前面的非空白字符不应是可选的,这将允许前有大写字母的ches。关于字符串。请根据您的示例进行测试或提供一个不起作用的示例。请用具体示例证明它不起作用。虽然我知道由于某些原因它违反Microsoft样式指南,但我通常使用CLR基元类型名称“string”或“Int32”代替“string”或“Int32”“int”,因此1)我的所有类型名在源代码中的颜色相同,2)我的变量声明中使用的类型名与调用这些类型的静态方法时必须使用的类型名匹配(“Int32.Parse(text)”),3)在处理多个.NET语言时,我可以使用相同的基元类型名称,4)对于“int”或“long”的大小没有混淆“是的,在不同的非.NET语言之间有所不同。除了约定和一些需要C#关键字的领域外,我想不出使用C#基元类型关键字有什么好处,比如VS2015之前的枚举类型声明(“Enum MyEnum:byte{}”)。我实际上想到了f