32

我有一个不错的 CamelCase 字符串,例如ImageWideNiceor ImageNarrowUgly。现在我想在它的子字符串中打破该字符串,例如Image, Wideor Narrow, and Niceor Ugly

我认为这可以简单地解决

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

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

您对拆分该字符串有更好的想法吗?

4

7 回答 7

62
s = 'nowIsTheTime'

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

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

?=pattern积极前瞻的一个例子。 它基本上匹配模式之前字符串中的一个点 它不消耗字符,也就是说,它不包含模式作为匹配的一部分。另一个例子:

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

在这种情况下,s匹配(仅第二个t匹配)但不被替换。感谢@Bryce和他的正则表达式文档链接。布莱斯安德森补充说:

匹配组?=开头的称为正向前瞻,这只是一种说法,即当正则表达式在确定是否匹配时查看字符时,它并没有使它们成为匹配的一部分。通常吃中间字符,但在这种情况下,匹配本身是空的,所以[那里]什么都没有。()split()

于 2010-10-22T14:03:43.823 回答
32

我知道这是旧的,但对于可能正在寻找它的其他人来说值得一提。在rails中你可以这样做: "NowIsTheTime".underscore.humanize

于 2011-11-15T21:26:36.003 回答
12

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

如果您知道字符串在这些形式中的哪一种,或者您想强制其中一种,Inflector 可以做到。

对于帕斯卡案例:

"NowIsTheTime".titleize

对于骆驼案:

"nowIsTheTime".titleize.camelize :lower
于 2014-08-31T15:47:12.280 回答
2

你有没有尝试过

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

?

于 2010-10-22T14:05:17.140 回答
2

事件虽然这是一个 Ruby 正则表达式问题,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"]
于 2010-10-22T14:50:56.613 回答
1

DigitalRoss的答案将无法识别 CamelCase 中嵌入的首字母缩略词。例如,它将“MyHTMLTricks”拆分为“My HTML 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"

The other thing I like about this approach is that it leaves the string a string, instead of transforming it into an array. If you really want the array, then just add a split at the end.

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

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

For the record, here is the original PHP code from PmWiki.

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);
}
于 2017-12-29T08:28:55.977 回答
1
I/p:- "ImageWideNice".scan(/[A-Z][a-z]+/).join(",")

O/p:- "Image,Wide,Nice"
于 2018-09-19T09:19:08.757 回答