如何在Ruby的子串中拆分CamelCase字符串?

时间:2010-10-22 13:59:22

标签: ruby regex string-split

我有一个很好的CamelCase字符串,例如ImageWideNiceImageNarrowUgly。现在我想在其子串中断掉该字符串,例如ImageWideNarrowNiceUgly

我认为这可以通过

简单解决
camelCaseString =~ /(Image)((Wide)|(Narrow))((Nice)|(Ugly))/

但奇怪的是,这只会填充$1$2,而不是$3

你有更好的想法来分割那个字符串吗?

7 个答案:

答案 0 :(得分:55)

s = 'nowIsTheTime'

s.split /(?=[A-Z])/

=> ["now", "Is", "The", "Time"]

?=pattern肯定前瞻的一个示例。它基本上匹配模式之前的字符串中的一个点。它不消耗字符,即是,它不包括模式作为匹配的一部分。另一个例子:

    irb> 'streets'.sub /t(?=s)/, '-'
=> "stree-s"

在这种情况下,s匹配(仅匹配第二个t)但未替换。感谢@Bryce和他的regexp doc link.布莱斯安德森补充说明:

  

?=匹配组开头的()称为正数   前瞻,这只是一种说法,而正则表达式   看着角色确定它是否匹配,事实并非如此   让他们成为比赛的一部分。 split()通常吃中间人   字符,但在这种情况下,匹配本身是空的,所以有   没有[那里]。

答案 1 :(得分:30)

我知道这是旧的,但值得一提的是其他可能正在寻找此事的人。在rails中,您可以执行此操作:"NowIsTheTime".underscore.humanize

答案 2 :(得分:8)

DigitalRoss的答案是正确的,因为它处理一般情况,你不知道它是否是严格的驼峰案(第一个字符小写)或Pascal案(第一个字母大写)。

如果您知道字符串中包含哪些形式,或者您想强制使用其中一种,Inflector可以执行此操作。

对于Pascal案例:

"NowIsTheTime".titleize

对于驼峰案例:

"nowIsTheTime".titleize.camelize :lower

答案 3 :(得分:2)

你试过吗

camelCaseString =~ /(Image)(Wide|Narrow)(Nice|Ugly)/

答案 4 :(得分:2)

事件虽然这是一个Ruby正则表达式问题而且answer by DigitalRoss是正确的并且因其简单性而闪耀,但我想添加一个Java答案:

// 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"]

答案 5 :(得分:1)

来自DigitalRoss的答案不会识别CamelCase中嵌入的首字母缩略词。例如,它会将“MyHTMLTricks”拆分为“My H T M L Tricks”而不是“My HTML Tricks”。

这是基于PmWikiAsSpaced()函数的另一个选项,它可以很好地对这样的案例敏感:

"MyHTMLTricks" \
.gsub(/([[:lower:]\\d])([[:upper:]])/, '\1 \2') \
.gsub(/([^-\\d])(\\d[-\\d]*( |$))/,'\1 \2') \
.gsub(/([[:upper:]])([[:upper:]][[:lower:]\\d])/, '\1 \2')

=> "My HTML Tricks"

我喜欢这种方法的另一个方面是它将字符串留给字符串,而不是将其转换为数组。如果你真的想要数组,那么只需在最后添加一个分割。

"MyHTMLTricks" \
.gsub(/([[:lower:]\\d])([[:upper:]])/, '\1 \2') \
.gsub(/([^-\\d])(\\d[-\\d]*( |$))/,'\1 \2') \
.gsub(/([[:upper:]])([[:upper:]][[:lower:]\\d])/, '\1 \2') \
.split

=> ["My", "HTML", "Tricks"]

记录中,这是PmWiki的原始PHP代码。

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);
}

答案 6 :(得分:0)

I/p:- "ImageWideNice".scan(/[A-Z][a-z]+/).join(",")

O/p:- "Image,Wide,Nice"