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

问题描述 投票:29回答:7

我有一个很好的CamelCase字符串,如ImageWideNiceImageNarrowUgly。现在我想在其子串中打破该字符串,例如ImageWideNarrow,以及NiceUgly

我认为这可以简单地解决

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

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

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

ruby regex string-split
7个回答
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.布莱斯安德森补充说明:

the?=at the()match组的开头被称为正向前瞻,这只是一种说法,虽然正则表达式正在查看角色是否匹配,但它并没有使它们成为匹配的一部分。 qazxswpo正常地吃掉中间的字符,但在这种情况下,匹配本身是空的,所以没有[那里]。


30
投票

我知道这是旧的,但值得一提的是其他可能正在寻找此事的人。在rails中你可以这样做:split()


8
投票

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

如果您知道字符串所在的这些表单中的哪一个,或者您想强制使用其中一个,Inflector就可以执行此操作。

对于Pascal案例:

"NowIsTheTime".underscore.humanize

对于驼峰案例:

"NowIsTheTime".titleize

2
投票

事件虽然这是一个Ruby正则表达式问题,而"nowIsTheTime".titleize.camelize :lower 是正确的,并且它的简单性令人眼前一亮,我想添加一个Java答案:

answer by DigitalRoss

2
投票

你有没有尝试过

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

?


1
投票

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

0
投票
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);
}
© www.soinside.com 2019 - 2024. All rights reserved.