正则表达式 - 将 PascalCase 转换为带下划线的小写格式

10

我正在尝试将PascalCase属性名称(例如Is24HourIs512)转换为JSON样式的小写带下划线(即is_24_houris_512),使用C#。

到目前为止,我已经做了一些工作,但它无法处理多个数字。

([A-Z])([A-Z0-9][a-z])|([a-z0-9])([A-Z0-9])

使用替换表达式($1$3_$2$4
例如,"Is24Hour" 变成 "Is_24_Hour"(然后通过 .ToLower() 转换为小写)。 但 "Is512" 变成 "Is_51_2"

2
顺便提一下,这也被称为蛇形命名法。https://en.m.wikipedia.org/wiki/Snake_case - Julian
3个回答

9

使用String.ToLower将字符串转换为小写。

对于正则表达式,以下似乎可以工作

((?<=.)[A-Z][a-zA-Z]*)|((?<=[a-zA-Z])\d+)

结合替换表达式:

_$1$2

这是一个完整的示例:
string strRegex = @"((?<=.)[A-Z][a-zA-Z]*)|((?<=[a-zA-Z])\d+)";
Regex myRegex = new Regex(strRegex, RegexOptions.Multiline);
string strTargetString = @"Is24Hour" + "\n" + 
    @"Is512" + "\n" + @"A12Hour4" + "\n" + 
    @"23AHourDay12" + "\n" + @"An8DAY512";

string strReplace = @"_$1$2";

return myRegex.Replace(strTargetString, strReplace).ToLower();

2
谢谢,那个完美地解决了问题。抱歉我忘记在我的问题中添加替换表达式 :) - Jamie
2
这根本不能正常工作。请参见此fiddle。即使使用提供的确切示例也会导致无效的结果字符串。例如,23AHourDay12在此代码中变成了23_ahourday_12,但实际上应该是23_a_hour_day_12 - vaindil
根本不起作用。FooBarBuzz 被转换为 foo_barbuzz - aradalvand

3
所接受的解决方案无法处理像"23AHourDay12"这样的字符串,它会生成"23_ahourday_12",但应该是"23_a_hour_day_12"(请参见@vaindil评论)。
以下是使用Linq而非Regex的解决方案:
public static class ExtensionMethods {
    public static string ToUnderscoreCase(this string str) {
        return string.Concat(str.Select((x, i) => i > 0 && char.IsUpper(x) ? "_" + x.ToString() : x.ToString())).ToLower();
    }
}

感谢Github用户@vkobel。来源:https://gist.github.com/vkobel/d7302c0076c64c95ef4b


2
public string PascalCaseToSnakeCase(string str) => Regex.Replace(str, "[A-Z0-9][0-9]*", "_$0").ToLower().Trim('_');

这个处理方式是否符合问题中对于“Is24Hour”和“Is512”中的数字的要求? - AdrianHHH

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接