6

で次の奇妙な動作を発見しましたString#split

"a\tb c\nd".split
=> ["a", "b", "c", "d"]

"a\tb c\nd".split(' ')
=> ["a", "b", "c", "d"]

"a\tb c\nd".split(/ /)
=> ["a\tb", "c\nd"]

ソース(2.0.0 の string.c) は 200 行以上あり、次のような一節が含まれています。

/* L 5909 */
else if (rb_enc_asciicompat(enc2) == 1) {
    if (RSTRING_LEN(spat) == 1 && RSTRING_PTR(spat)[0] == ' '){
        split_type = awk;
    }
}

後で、awk分割型のコードでは、実際の引数は使用されなくなり、プレーンと同じように動作しますsplit

  • これがどういうわけか壊れていると感じている人はいますか?
  • これには正当な理由がありますか?
  • このような「魔法」は、ほとんどの人が Ruby で考えるよりも頻繁に発生するのでしょうか?
4

2 に答える 2

4

これは、Perl のsplit()動作と一致しています。これは、 Gnuawk に基づいていますsplit()。したがって、これは Unix に起源を持つ長年の伝統です。

perldocからsplit: _

別の特殊なケースとして、 split は、 PATTERN が省略されているか、単一の空白文字で構成されるリテラル文字列 ( ' ' や "\x20" などですが、 / / は除く) のいずれかの場合に、コマンド ライン ツール awk のデフォルトの動作をエミュレートします。この場合、分割が発生する前に EXPR の先頭の空白が削除され、代わりに PATTERN が /\s+/ であるかのように扱われます。特に、これは、連続する空白 (単一の空白文字だけでなく) が区切り文字として使用されることを意味します。ただし、この特別な処理は、文字列 " " の代わりにパターン / / を指定することで回避できます。これにより、単一の空白文字のみを区切り文字にすることができます。

于 2013-04-30T14:59:36.877 に答える
2

ドキュメント、特にこの部分を確認してください。

pattern が String の場合、str を分割するときにその内容が区切り文字として使用されます。pattern が単一のスペースの場合、str は空白で分割され、先頭の空白と連続する空白文字は無視されます。

パターンが省略された場合、$; の値。使用されている。もし$; nil (デフォルト) の場合、str は ` ' が指定されたかのように空白で分割されます。

正規表現を使用して文字列を分割できます。

于 2013-04-30T13:44:31.070 に答える