可以使用哪个正则表达式进行以下转换?
City -> CITY
FirstName -> FIRST_NAME
DOB -> DOB
PATId -> PAT_ID
RoomNO -> ROOM_NO
以下几乎可行 - 它只是在单词的开头添加了一个额外的下划线:
var rgx = @"(?x)( [A-Z][a-z,0-9]+ | [A-Z]+(?![a-z]) )";
var tests = new string[] { "City",
"FirstName",
"DOB",
"PATId",
"RoomNO"};
foreach (var test in tests)
Console.WriteLine("{0} -> {1}", test,
Regex.Replace(test, rgx, "_$0").ToUpper());
// output:
// City -> _CITY
// FirstName -> _FIRST_NAME
// DOB -> _DOB
// PATId -> _PAT_ID
// RoomNO -> _ROOM_NO
答案 0 :(得分:16)
从John M Gant的想法中加入下划线然后大写,我认为这个正则表达式应该有效:
([A-Z])([A-Z][a-z])|([a-z0-9])([A-Z])
替换为:
$1$3_$2$4
您可以重命名捕获区域,以使替换字符串更好一些。只有$ 1或$ 3应该有一个值,相同的是2美元和4美元。一般的想法是在以下情况下添加下划线:
希望这有帮助。
答案 1 :(得分:11)
我建议使用简单的Regex插入下划线,然后string.ToUpper()
转换为大写。
Regex.Replace(test, @"(\p{Ll})(\p{Lu})", "$1_$2").ToUpper()
这是两个操作而不是一个,但对我而言,它比一个复杂的正则表达式替换更容易阅读。
答案 2 :(得分:2)
我可能想出一个可以做到这一点的正则表达式...但我相信变革性的正则表达式可能不是正确的答案。我建议你拿走你已经拥有的东西,然后将第一个字符(前导下划线)从输出中删除。 CPU时间可能与此相同或更少,并且您的编码时间无关紧要。
尝试:&lt; - 误导和失败尝试梦想我说的是一个愚蠢的想法。< / p>
(?x)(.)( [A-Z][a-z,0-9]+ | [A-Z]+(?![a-z]) )
并将代码更改为输出$ 0_ $ 1而不是_ $ 0
答案 3 :(得分:1)
看起来像Rails does it使用多个正则表达式。
var rgx = @"([A-Z]+)([A-Z][a-z])";
var rgx2 = @"([a-z\d])([A-Z])";
foreach (var test in tests)
{
var result = Regex.Replace(test, rgx, "$1_$2");
result = Regex.Replace(result, rgx2, "$1_$2");
result = result.ToUpper();
Console.WriteLine("{0} -> {1}", test, result);
}
答案 4 :(得分:1)
我意识到这是一个老问题,但它仍然经常出现,所以我决定分享我自己的方法。
不是试图用替换来做,而是想找到字符串中的所有“单词”,然后将它们转换为大写并加入:
var tests = new string[] { "City",
"FirstName",
"DOB",
"PATId",
"RoomNO"};
foreach (var test in tests)
Console.WriteLine("{0} -> {1}", test,
String.Join("_", new Regex(@"^(\p{Lu}(?:\p{Lu}*|[\p{Ll}\d]*))*$")
.Match(test)
.Groups[1]
.Captures
.Cast<Capture>()
.Select(c => c.Value.ToUpper())));
不是非常简洁,但允许你专注于定义“单词”是什么,而不是与锚点,分隔符等等进行斗争。在这种情况下,我将一个单词定义为以大写字母开头,后跟一系列大写字母或混合使用小写和大写字母的单词。我本可以想要分开数字序列。 "^(\p{Lu}(?:\p{Lu}*|\p{Ll}*)|\d+)*$"
可以解决问题。或许我想将数字作为前一个大写单词的一部分,然后我做"^(\p{Lu}(?:[\p{Lu}\d]*|[\p{Ll}\d]*))*$"
。
答案 5 :(得分:0)
这里没有javascript答案,所以也可以添加它。
(这是使用@John McDonald的正则表达式)
var text = "fooBar barFoo";
var newText = text.replace(/([A-Z])([A-Z][a-z])|([a-z0-9])([A-Z])/g, "$1$3_$2$4");
newText.toLowerCase()