正则表达式.骆驼案要强调.忽略第一个匹配项
本文关键字:第一个 正则表达式 | 更新日期: 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();
- 这适用于
PascalCase
和camelCase
。 - 它不会创建前导或尾随下划线。
- 它在字符串中保留了任何非单词字符和下划线序列,因为它们似乎是故意的,例如
__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"
用于替换。因此,您使用捕获的字符串进行替换,并使用前导.
确定您没有捕获字符串的第一个字符。