我正在尝试将骆驼案转换为蛇案。
赞:
"LiveKarma"
-> "live_karma"
"youGO"
-> "you_g_o"
我似乎无法让第二个示例那样工作。它始终输出为'you_go'。如何获取输出“ you_g_o”的信息
我的代码:
(Regex.Replace(line, "(?<=[a-z0-9])[A-Z]", "_$0", RegexOptions.Compiled)).ToLowerInvariant()
答案 0 :(得分:2)
由于将缩写转换为单独单词的选项不适合很多人,我在 EF Core 代码库中找到了完整的解决方案。
以下是代码工作原理的几个示例:
TestSC -> test_sc
testSC -> test_sc
TestSnakeCase -> test_snake_case
testSnakeCase -> test_snake_case
TestSnakeCase123 -> test_snake_case123
_testSnakeCase123 -> _test_snake_case123
test_SC -> test_sc
我重写了一点,以便您可以将其复制为现成的字符串扩展:
using System;
using System.Globalization;
using System.Text;
namespace Extensions
{
public static class StringExtensions
{
public static string ToSnakeCase(this string text)
{
if (string.IsNullOrEmpty(text))
{
return text;
}
var builder = new StringBuilder(text.Length + Math.Min(2, text.Length / 5));
var previousCategory = default(UnicodeCategory?);
for (var currentIndex = 0; currentIndex < text.Length; currentIndex++)
{
var currentChar = text[currentIndex];
if (currentChar == '_')
{
builder.Append('_');
previousCategory = null;
continue;
}
var currentCategory = char.GetUnicodeCategory(currentChar);
switch (currentCategory)
{
case UnicodeCategory.UppercaseLetter:
case UnicodeCategory.TitlecaseLetter:
if (previousCategory == UnicodeCategory.SpaceSeparator ||
previousCategory == UnicodeCategory.LowercaseLetter ||
previousCategory != UnicodeCategory.DecimalDigitNumber &&
previousCategory != null &&
currentIndex > 0 &&
currentIndex + 1 < text.Length &&
char.IsLower(text[currentIndex + 1]))
{
builder.Append('_');
}
currentChar = char.ToLower(currentChar, CultureInfo.InvariantCulture);
break;
case UnicodeCategory.LowercaseLetter:
case UnicodeCategory.DecimalDigitNumber:
if (previousCategory == UnicodeCategory.SpaceSeparator)
{
builder.Append('_');
}
break;
default:
if (previousCategory != null)
{
previousCategory = UnicodeCategory.SpaceSeparator;
}
continue;
}
builder.Append(currentChar);
previousCategory = currentCategory;
}
return builder.ToString();
}
}
}
您可以在这里找到原始代码: https://github.com/efcore/EFCore.NamingConventions/blob/main/EFCore.NamingConventions/Internal/SnakeCaseNameRewriter.cs
答案 1 :(得分:1)
下面的伪代码。本质上,检查每个字符是否为大写,然后添加一个_
,然后将该字符添加为小写
var newString = s.subString(0,1).ToLower();
foreach (char c in s.SubString(1,s.length-1))
{
if (char.IsUpper(c))
{
newString = newString + "_";
}
newString = newString + c.ToLower();
}
答案 2 :(得分:1)
这是一种扩展方法,可将文本转换为蛇形情况:
using System.Text;
public static string ToSnakeCase(this string text)
{
if(text == null) {
throw new ArgumentNullException(nameof(text));
}
if(text.Length < 2) {
return text;
}
var sb = new StringBuilder();
sb.Append(char.ToLowerInvariant(text[0]));
for(int i = 1; i < text.Length; ++i) {
char c = text[i];
if(char.IsUpper(c)) {
sb.Append('_');
sb.Append(char.ToLowerInvariant(c));
} else {
sb.Append(c);
}
}
return sb.ToString();
}
将其放入某个位置的静态类(例如,StringExtensions
)中,并像这样使用它:
string text = "LiveKarma";
string snakeCaseText = text.ToSnakeCase();
// snakeCaseText => "live_karma"
答案 3 :(得分:0)
RegEx解决方案
一个快速的互联网搜索出现this site,它使用RegEx给出了答案,我不得不对其进行修改以获取Value
部分,以便它可以在我的计算机上工作(但它具有RegEx您正在寻找)。我还修改了它以处理null
输入,而不是抛出异常:
public static string ToSnakeCase2(string str)
{
var pattern =
new Regex(@"[A-Z]{2,}(?=[A-Z][a-z]+[0-9]*|\b)|[A-Z]?[a-z]+[0-9]*|[A-Z]|[0-9]+");
return str == null
? null
: string
.Join("_", pattern.Matches(str).Cast<Match>().Select(m => m.Value))
.ToLower();
}
非RegEx解决方案
对于非正则表达式解决方案,我们可以执行以下操作:
string.Split
以一个空数组进行分割作为在所有空白处进行分割的第一个参数'_'
字符将这些部分重新结合在一起'_'
前缀所有大写字符,并用小写字母_
字符上分割并重新加入结果字符串,以删除多个并发下划线("__"
)的任何实例,并删除该字符的任何前导或尾随实例。例如:
public static string ToSnakeCase(string str)
{
return str == null
? null
: string.Join("_", string.Concat(string.Join("_", str.Split(new char[] {},
StringSplitOptions.RemoveEmptyEntries))
.Select(c => char.IsUpper(c)
? $"_{c}".ToLower()
: $"{c}"))
.Split(new[] {'_'}, StringSplitOptions.RemoveEmptyEntries));
}