我有一个很好的CamelCase字符串,如ImageWideNice
或ImageNarrowUgly
。现在我想在其子串中打破该字符串,例如Image
,Wide
或Narrow
,以及Nice
或Ugly
。
我认为这可以简单地解决
camelCaseString =~ /(Image)((Wide)|(Narrow))((Nice)|(Ugly))/
但奇怪的是,这只会填补$1
和$2
,但不会填充$3
。
你有更好的想法拆分那个字符串吗?
s = 'nowIsTheTime'
s.split /(?=[A-Z])/
=> ["now", "Is", "The", "Time"]
?=pattern
是积极前瞻的一个例子。它基本上匹配模式之前的字符串中的一个点。它不消耗字符,也就是说,它不包含模式作为匹配的一部分。另一个例子:
irb> 'streets'.sub /t(?=s)/, '-'
=> "stree-s"
在这种情况下,s
匹配(只有第二个t
匹配)但没有被替换。感谢@Bryce和他的regexp doc link.布莱斯安德森补充说明:
the
?=
at the()
match组的开头被称为正向前瞻,这只是一种说法,虽然正则表达式正在查看角色是否匹配,但它并没有使它们成为匹配的一部分。 qazxswpo正常地吃掉中间的字符,但在这种情况下,匹配本身是空的,所以没有[那里]。
我知道这是旧的,但值得一提的是其他可能正在寻找此事的人。在rails中你可以这样做:split()
DigitalRoss的答案是正确的,因为它处理一般情况,你不知道它是严格的驼峰情况(第一个字符小写)还是Pascal情况(第一个字母大写)。
如果您知道字符串所在的这些表单中的哪一个,或者您想强制使用其中一个,Inflector就可以执行此操作。
对于Pascal案例:
"NowIsTheTime".underscore.humanize
对于驼峰案例:
"NowIsTheTime".titleize
事件虽然这是一个Ruby正则表达式问题,而"nowIsTheTime".titleize.camelize :lower
是正确的,并且它的简单性令人眼前一亮,我想添加一个Java答案:
answer by DigitalRoss
你有没有尝试过
// this regex doesn't work perfect with Java and other regex engines
"NowIsTheTime".split("(?=[A-Z])"); // ["", "Now", "Is", "The", "Time"]
// this regex works with first uppercase or lowercase characters
"NowIsTheTime".split("(?!(^|[a-z]|$))"); // ["Now", "Is", "The", "Time"]
"nowIsTheTime".split("(?!(^|[a-z]|$))"); // ["now", "Is", "The", "Time"]
?
camelCaseString =~ /(Image)(Wide|Narrow)(Nice|Ugly)/
的答案不会识别CamelCase中嵌入的首字母缩略词。例如,它会将“MyHTMLTricks”拆分为“My H T M L Tricks”而不是“My HTML Tricks”。
这是另一个基于DigitalRoss中的AsSpaced()
函数的选项,它可以很好地对这样的情况敏感:
PmWiki
我喜欢这种方法的另一件事是它将字符串留下一个字符串,而不是将其转换为数组。如果你真的想要数组,那么只需在最后添加一个分割。
"MyHTMLTricks" \
.gsub(/([[:lower:]\\d])([[:upper:]])/, '\1 \2') \
.gsub(/([^-\\d])(\\d[-\\d]*( |$))/,'\1 \2') \
.gsub(/([[:upper:]])([[:upper:]][[:lower:]\\d])/, '\1 \2')
=> "My HTML Tricks"
为了记录,这是来自PmWiki的原始PHP代码。
"MyHTMLTricks" \
.gsub(/([[:lower:]\\d])([[:upper:]])/, '\1 \2') \
.gsub(/([^-\\d])(\\d[-\\d]*( |$))/,'\1 \2') \
.gsub(/([[:upper:]])([[:upper:]][[:lower:]\\d])/, '\1 \2') \
.split
=> ["My", "HTML", "Tricks"]
function AsSpaced($text) {
$text = preg_replace("/([[:lower:]\\d])([[:upper:]])/", '$1 $2', $text);
$text = preg_replace('/([^-\\d])(\\d[-\\d]*( |$))/', '$1 $2', $text);
return preg_replace("/([[:upper:]])([[:upper:]][[:lower:]\\d])/", '$1 $2', $text);
}