web-dev-qa-db-ja.com

RubyでCamelCase文字列を部分文字列に分割するにはどうすればよいですか?

ImageWideNiceImageNarrowUglyなどの素敵なキャメルケース文字列があります。次に、その文字列をImageWideまたはNarrow、およびNiceまたはUglyなどの部分文字列で分割します。

これは簡単に解決できると思いました

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

しかし不思議なことに、これは$1$2のみを埋め、$3は埋めません。

その文字列を分割するためのより良いアイデアがありますか?

30
bastibe
_s = 'nowIsTheTime'

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

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

_?=pattern_はポジティブ先読みの例です。これは基本的にパターンの直前の文字列内のポイントと一致します。 。文字を消費しません。つまり、一致の一部としてpatternが含まれません。 。もう一つの例:

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

この場合、sは一致しますが(2番目のtのみが一致します)、置き換えられません。 @ Bryce と彼の regexp doc link。 に感謝します。BryceAndersonが説明を追加します。

_?=_ matchグループの先頭にあるThe _()_は、ポジティブ先読みと呼ばれます。これは、正規表現が検索されている間、一致するかどうかを判断する際の文字では、一致の一部にはなりません。 split()通常は中間の文字を食べますが、この場合、一致自体は空であるため、何もありません。

55
DigitalRoss

私はこれが古いことを知っていますが、これを探しているかもしれない他の人のために言及する価値があります。 Railsでこれを行うことができます:"NowIsTheTime".underscore.humanize

30
Fitmo Appadmin

DigitalRossの答えは、厳密なキャメルケース(最初の文字の小文字)かパスカルケース(最初の文字の大文字)かがわからない一般的なケースを処理するため、正しいです。

これらの形式のどちらに文字列があるかがわかっている場合、またはどちらか一方を強制したい場合は、Inflectorがそれを実行できます。

パスカルケースの場合:

"NowIsTheTime".titleize

キャメルケースの場合:

"nowIsTheTime".titleize.camelize :lower
8
Tim Scott

これは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"]
2
splash

やってみました

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

2
pjmorse

DigitalRoss からの回答は、CamelCaseに埋め込まれている頭字語を認識しません。たとえば、「MyHTMLTricks」を「MyHTMLTricks」ではなく「MyHT MLTricks」に分割します。

PmWikiAsSpaced()関数に基づく別のオプションがあります。これは、次のようなケースに敏感であるという素晴らしい仕事をします。

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

=> "My HTML Tricks"

このアプローチで私が気に入っているもう1つの点は、文字列を配列に変換するのではなく、文字列のままにすることです。本当に配列が必要な場合は、最後に分割を追加するだけです。

"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);
}
1
EFC
I/p:- "ImageWideNice".scan(/[A-Z][a-z]+/).join(",")

O/p:- "Image,Wide,Nice"
0
Prashant Kajale