split

調べてみると、プログラミング言語によって、split の細かい挙動が異なるのであった。

Perl, Ruby の場合

% ruby -e 'p "a-b--c-".split /-/'  
["a", "b", "", "c"]

% ruby -e 'p "a-b--c-".split /-/, -1'
["a", "b", "", "c", ""]

% ruby -e 'p "a-b--c-".split /(-)/'
["a", "-", "b", "-", "", "-", "c", "-"]

% ruby -e 'p "abc".split //'
["a", "b", "c"]
% perl -MData::Dumper -e 'print Dumper([split /-/, "a-b--c-"])'
$VAR1 = [
          'a',
          'b',
          '',
          'c'
        ];

% perl -MData::Dumper -e 'print Dumper([split /-/, "a-b--c-", -1])'
$VAR1 = [
          'a',
          'b',
          '',
          'c',
          ''
        ];

% perl -MData::Dumper -e 'print Dumper([split /(-)/, "a-b--c-"])' 
$VAR1 = [
          'a',
          '-',
          'b',
          '-',
          '',
          '-',
          'c',
          '-'
        ];

% perl -MData::Dumper -e 'print Dumper([split //, "abc"])' 
$VAR1 = [
          'a',
          'b',
          'c'
        ];

PerlRuby は同じ動き。

  • 分割の結果、空文字となった末尾の要素は削除
    • 分割数に負数を指定すると削除されない
  • 正規表現にキャプチャがある場合は、キャプチャされた内容が戻り値に格納
  • 空の正規表現の場合は文字ごとに分割

Python の場合

% python -c 'import re; print repr(re.split("-", "a-b--c-"))'
['a', 'b', '', 'c', '']

% python -c 'import re; print repr(re.split("(-)", "a-b--c-"))'
['a', '-', 'b', '-', '', '-', 'c', '-', '']

% python -c 'import re; print repr(re.split("", "abc"))'
['abc']
  • 末尾の空文字は削除されない
  • 正規表現にキャプチャがある場合の動作は Perl, Ruby と同様
  • 空の正規表現の場合は分割されない

Java の場合

Groovy というか、Java の仕様。

% groovy -e 'println("a-b--c-".split(/-/))'
[a, b, , c]

% groovy -e 'println("a-b--c-".split(/(-)/, -1))'
[a, b, , c, ]

% groovy -e 'println("a-b--c-".split(/(-)/))'
[a, b, , c]

% groovy -e 'println("abc".split(""))'    
[, a, b, c]

% groovy -e 'println("abc".split("", -1))'
[, a, b, c, ]
  • 末尾の空文字は削除される
    • 分割数に負数を指定すると削除されない
  • 正規表現にキャプチャがあっても関係なし
  • 空の正規表現を指定すると文字ごとに分割
    • 先頭と末尾に空文字が入る
    • 分割数の指定がないと末尾の空文字は削除

JavaScript の場合

Java に標準で組み込まれている Rhino を使ってみる。

% jrunscript -e 'println("a-b--c-".split(/-/).toSource())'      
["a", "b", "", "c", ""]

% jrunscript -e 'println("a-b--c-".split(/(-)/).toSource())'
["a", "-", "b", "-", "", "-", "c", "-", ""]

% jrunscript -e 'println("abc".split(new RegExp()).toSource())'
["a", "b", "c"]
  • 末尾の空文字は削除されない
  • 正規表現にキャプチャがある場合の動作 Perl, Ruby と同様
  • 空の正規表現を指定した場合は文字ごとに分割(Perl, Ruby と同様)

末尾にデリミタが来る場合なんかを考えると分割数を常に指定しておいたほうが無難かなぁ。
しかし、末尾の空文字を削除するのは何なんだろな。