正则表达式.骆驼案要强调.忽略第一个匹配项

本文关键字:第一个 正则表达式 | 更新日期: 2023-09-27 18:31:13

例如:

thisIsMySample 

应该是:

this_Is_My_Sample

我的代码:

System.Text.RegularExpressions.Regex.Replace(input, "([A-Z])", "_$0", System.Text.RegularExpressions.RegexOptions.Compiled);

它工作正常,但如果输入更改为:

ThisIsMySample

输出将是:

_This_Is_My_Sample

如何忽略首次出现?

正则表达式.骆驼案要强调.忽略第一个匹配项

非正则表达式解决方案

string result = string.Concat(input.Select((x,i) => i > 0 && char.IsUpper(x) ? "_" + x.ToString() : x.ToString())); 

似乎也很快:正则表达式:2569ms,C#:1489ms

Stopwatch stp = new Stopwatch();
stp.Start();
for (int i = 0; i < 1000000; i++)
{
    string input = "ThisIsMySample";
    string result = System.Text.RegularExpressions.Regex.Replace(input, "(?<=.)([A-Z])", "_$0",
            System.Text.RegularExpressions.RegexOptions.Compiled);
}
stp.Stop();
MessageBox.Show(stp.ElapsedMilliseconds.ToString());
// Result 2569ms
Stopwatch stp2 = new Stopwatch();
stp2.Start();
for (int i = 0; i < 1000000; i++)
{
    string input = "ThisIsMySample";
    string result = string.Concat(input.Select((x, j) => j > 0 && char.IsUpper(x) ? "_" + x.ToString() : x.ToString()));
}
stp2.Stop();
MessageBox.Show(stp2.ElapsedMilliseconds.ToString());
// Result: 1489ms

您可以使用回溯来确保每个匹配项前面至少有一个字符:

System.Text.RegularExpressions.Regex.Replace(input, "(?<=.)([A-Z])", "_$0",
                      System.Text.RegularExpressions.RegexOptions.Compiled);

前瞻和后瞻允许您对匹配项周围的文本做出断言,而无需在匹配项中包含该文本。

也许喜欢;

var str = Regex.Replace(input, "([A-Z])", "_$0", RegexOptions.Compiled);
if(str.StartsWith("_"))
   str = str.SubString(1);
// (Preceded by a lowercase character or digit) (a capital) => The character prefixed with an underscore
var result = Regex.Replace(input, "(?<=[a-z0-9])[A-Z]", m => "_" + m.Value);
result = result.ToLowerInvariant();
  • 这适用于PascalCasecamelCase
  • 它不会创建前导或尾随下划线。
  • 它在字符串中保留了任何非单词字符和下划线序列,因为它们似乎是故意的,例如 __HiThere_Guys变得__hi_there_guys.
  • 数字后缀(有意)被视为单词的一部分,例如 NewVersion3变得new_version3.
  • 数字前缀遵循原始大小写,例如 3VersionsHere变得3_versions_here,但3rdVersion变得3rd_version
  • 不幸的是,Microsoft的大写公约中建议的大写双字母首字母缩略词(例如在IDNumber中,ID将被视为一个单独的单词)不受支持,因为它们与其他情况冲突。总的来说,我建议抵制这一准则,因为它似乎是大写首字母缩略词惯例的任意例外。坚持IdNumber.
您需要

修改正则表达式以不匹配第一个字符,方法是定义要忽略第一个字符

.([A-Z])

上面的正则表达式只是排除了第一个出现的每个字符,并且由于它不在大括号中,因此它将在匹配组中。

现在你需要匹配第二组,就像Bibhu指出的那样:

System.Text.RegularExpressions.Regex.Replace(s, "(.)([A-Z])", "$1_$2", System.Text.RegularExpressions.RegexOptions.Compiled);

详细阐述sa_ddam213的解决方案,我的扩展了这个:

public static string GetConstStyleName(this string value)
        {
            return string.Concat(value.Select((x, i) =>
            {
                //want to avoid putting underscores between pairs of upper-cases or pairs of numbers, or adding redundant underscores if they already exist.
                bool isPrevCharLower = (i == 0) ? false : char.IsLower(value[i - 1]);
                bool isPrevCharNumber = (i == 0) ? false : char.IsNumber(value[i - 1]);
                return (isPrevCharLower && (char.IsUpper(x) || char.IsNumber(x))) //lower-case followed by upper-case or number needs underscore
                    || (isPrevCharNumber && (char.IsUpper(x))) //number followed by upper-case needs underscore
                    ? "_" + x.ToString() : x.ToString();
            })).ToUpperInvariant();
        }

使用 ".([A-Z])" 作为正则表达式,然后"_$1"用于替换。因此,您使用捕获的字符串进行替换,并使用前导.确定您没有捕获字符串的第一个字符。