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

后来,在awksplit 类型的代码中,实际参数甚至不再使用,并且与 plain 相同split

  • 有没有人觉得这有点坏了?
  • 这有充分的理由吗?
  • 在 Ruby 中,这种“魔法”是否比大多数人想象的更频繁?
4

2 回答 2

4

这与 Perl 的split()行为一致。这又是基于Gnuawk split()。因此,它起源于 Unix,是一个由来已久的传统。

perldoc开始split

作为另一种特殊情况,当 PATTERN 被省略或由单个空格字符组成的文字字符串(例如 ' ' 或 "\x20" ,但不是例如 // )时, split 模拟命令行工具 awk 的默认行为。在这种情况下,EXPR 中的任何前导空格在拆分发生之前都会被删除,而 PATTERN 则被视为 /\s+/ ;特别是,这意味着任何连续的空格(不仅仅是单个空格字符)都用作分隔符。但是,可以通过指定模式 // 而不是字符串 " " 来避免这种特殊处理,从而只允许单个空格字符作为分隔符。

于 2013-04-30T14:59:36.877 回答
2

查看文档,尤其是这部分:

如果pattern是一个String,那么它的内容在分割str时作为分隔符。如果 pattern 是单个空格,则 str 在空格上拆分,忽略前导空格和连续空格字符的运行。

如果 pattern 被省略,$ 的值;用来。如果 $; 为 nil(这是默认值),str 在空格上拆分,就像指定了 ` '。

您可以使用正则表达式来拆分字符串。

于 2013-04-30T13:44:31.070 回答