[#954] Rational — keiju@... (Keiju ISHITSUKA)

けいじゅ@SHLジャパンです.

23 messages 1996/10/30
[#955] Re: Rational — matz@... (Yukihiro Matsumoto) 1996/10/30

まつもと ゆきひろです.

[#968] Re: Rational 1996/10/31

けいじゅ@SHLジャパンです.

[ruby-list:907] [REQ]Get Strings!<4> SPLIT

From: Shin-ichiro Hara <sinara@...>
Date: 1996-10-27 10:26:45 UTC
List: ruby-list #907
原です。

(9)救助のある split

これも良くある状況だと思いますが、

95/12/21 14:47:58 [2:matz caelum.co.] Re: ruby-0.95

というレコードから、

['95/12/21', '14:47:58', '[2:matz caelum.co.]', 'Re: ruby-0.95']

という配列をあえて split を使って取り出すという問題を考えます。

まず、現状のレポートから。

---------------------^ split_test.rb
#!/usr/local/bin/ruby
$lim = ARGV[0]
$str = "95/12/21 14:47:58 [2:matz caelum.co.] Re: ruby-0.95"
$arr = $str.split(/( |\[[^]]+\])/, $lim)
$n = 1
for $x in $arr
  print "#$n:(#$x)\n"
  $n += 1
end
---------------------$ split_test.rb
---------------------^ split_test.pl
#!/usr/local/bin/perl
$lim = $ARGV[0];
$str = "95/12/21 14:47:58 [2:matz caelum.co.] Re: ruby-0.95";
@arr = split(/( |\[[^]]+\])/, $str, $lim);
$n = 1;
for $x (@arr) {
    print "$n:($x)\n";
    $n++;
}
---------------------$ split_test.pl

という2つのスクリプトをパラメータ無しに起動すると、
ruby, perl ともに

-----------------^
1:(95/12/21)
2:( )
3:(14:47:58)
4:( )
5:()
6:([2:matz caelum.co.])
7:()
8:( )
9:(Re:)
10:( )
11:(ruby-0.95)
-----------------$

という出力が選られます。ruby もドキュメントには無い^^;
けれど、括弧つきのセパレータに対応していたのですね。

で、limit のパラメータをつけると、フィールドの数え方に ruby
と perl ではポリシーの違いがある事がわかります。

-----------------^
bash# ./split_test.rb 5
1:(95/12/21)
2:( )
3:(14:47:58)
4:( )
5:()
6:( Re: ruby-0.95)
-----------------$
-----------------^
bash# ./split_test.pl 5
1:(95/12/21)
2:( )
3:(14:47:58)
4:( )
5:()
6:([2:matz caelum.co.])
7:()
8:( )
9:(Re: ruby-0.95)
-----------------$

つまり perl では、セパレータの括弧で出てきた配列を数に入れない
ようですね。この違いについては、perl に合わせてもいいし、この
ままにしてもいいと思います。(ただし、ruby については、ちょっ
とバグがありますね。)

更に split のセパレータを /( |\[[^]]+\])/ から / |(\[[^]]+\])/
に変えて実験すると、新たな仕様の違いがあらわになります。

-----------------^
bash# ./split_test.rb 6
1:(95/12/21)
2:(14:47:58)
3:()
4:([2:matz caelum.co.])
5:()
6:(Re: ruby-0.95)
-----------------$
-----------------^
bash# ./split_test.pl 5
1:(95/12/21)
2:()
3:(14:47:58)
4:()
5:()
6:([2:matz caelum.co.])
7:()
8:()
9:(Re: ruby-0.95)
-----------------$

つまり ruby は \1 が nil になる時、それを省いているが、perl は
 '' として出力します。もちろん、ruby の挙動は合理的だと思います。
ドキュメントにしておいた方がいいですね。


で、表題の「救助のある」split ですけど、こんなこと出来たらいいな
と思うのですけど、

$str = "95/12/21 14:47:58 [2:matz caelum.co.] Re: ruby-0.95"
$arr = $str.split(/ /, /\[[^]]+\]/, 4)

だけで、

$arr = ['95/12/21', '14:47:58', '[2:matz caelum.co.]', 'Re: ruby-0.95']

となるというものです。つまり、第二引数のパターンにマッチする文字列を
掬いあげながら split するわけです。

これなら、例えば "" によるエスケープのある SVC 形式のデータでも(意外
にこれ難しいんですが)、split(/,/, /"[^"]+"/) 一発で分割出来ます。第二
引数の正規表現に括弧をつけるどうか、「1,abc",efg"h,jkl」などはどう分け
るかなど考えるべきこともありますけれど。(['1', 'abc"', 'efg"h', 'jkl'] 
かな。)いかがでしょうか。

(つづく?)
----------------------------------------------------------
                                                  原信一郎

In This Thread

Prev Next