splitで要素を分ける方法について

[上に] [前に] [次に]
kofuku [E-Mail] 1999/05/19(水) 16:11:50
文字列を、ある文字で分けるコマンドとして、perlには、splitがありますが、
例えば、
$x = 'a<>b<>c<>"d<>e"<>f';
といった、文字列$xを
@y = split(/<>/, $x);
で実行した場合、結果は,@yに
(a,b,c,"d,e",f)
が帰ってきますが、ここで、
(a,b,c,d<>e,f)
が、戻ってくるようにするには、どの様にしたらよいのでしょうか?
つまり、ある区切り文字で連結された要素の中に、区切り文字が入っていた場合にはどの様にしたらよいのか
といったことですが、ご教授方よろしくお願いします。
因みに、csv ファイルの場合は
@y = ();
push (@y, $+) while $x =~ m{ "([^\"\\]*(?:\\.[^\"\\]*)*)",? | ([^,]+),?| , }gx;
push (@y, undef) if substr ( $x, -1, 1) eq ',' ;

でうまくいったのですが、これのカンマの所を<>に置き換えると、最後の要素が出てこないのですが、


B-Cus 1999/05/19(水) 22:57:54
ちょっといまいちなコードかもしれないけど…

 $_ = 'a<>b<>c<>"d<>e"<>f';
 while ($_){
  s/^"(.*?)"(<>|$)// || s/^(.*?)(<>|$)//;
  push(@y,$1);
 }

なえ 1999/05/20(木) 11:25:20
ややこしいこと考えずに、分割する前に""で囲まれた部分の<>を別の文字列に置き換えちゃえばいいんじゃない?
$x =  'a<>b<>c<>"d<>e"<>f';
$x =~ s/&/&&/g; # <&>という文字列が入力された場合の対応
$x =~ s/(".*?)<>(.*?")/$1<&>$2/g;
@y = split(/(?:"|<>)+/, $x);
@y = map{s/<&>/<>/; s/&&/&/; $_}(@y);

これで、どうでしょうか?

K's K [E-Mail] 1999/08/10(火) 01:34:32
kofukuさんのデータ内にカンマが含まれる場合のcsvの処理を見させて貰って、使わせていただきました。
すると、うまく切り取ることが出来ない行があって、その行には、元のデータにダブルクオーテーションマークが含まれるていて("tohoho")、それが、("""tohoho""")のようにcsvに変換されていました。
やってみたのですが、Perlを始めて2ヶ月程度では歯が立ちません。
どうかご教授願います。なお、元のデータにコンマとダブルクオーテーションマークがともに含まれている場合もあるので、

a,"a,b","""a""","""a, b, and c"""

を、正しく

a と a,b と"a"と"a, b, and c"に区切る方法ということになると思います。よろしくお願いいたします。

B-Cus 1999/08/10(火) 05:08:36
うまくいくかどうか自信はないけど
 $_='a,"a,b","""a""","""a, b, and c"""';
 while ($_){
  s/^("*)(".*?")\1(,|$)// || s/^()(.*?)(,|$)//;
  print "$2\n";
 }
とか。

K's K 1999/08/11(水) 01:40:02
B-Cusさんのをやってみたら2つめが、"a,b"と表示されました。
なお、単にCSVといってもソフトによって保存形式が違うんですね。
a a,b "a" "a,b" a,"b" "a","b"
が、Windows版のExcel(95)では
a,"a,b","""a""","""a,b""","a,""b""","""a"",""b"""
となり三四郎8で保存すると、
"a","a,b",""a"",""a,b"","a,"b"",""a","b""
となりました。私の使いたいデータは桐の7で、これを「テキストで書き出す」とExcelと同じになりました。
ややっこしい例を増やしてしまったようですが、Excel形式のcsvでよろしくお願い致します。

K's K 1999/08/11(水) 01:44:25
上の3行目が、書いている間は離れていたのですが送信するとくっついて見づらくなってしまいました。
a  a,b  "a"  "a,b"  a,"b"  "a","b"
の6つです。

Aurai 1999/08/11(水) 05:28:49
長くなってしまいましたが
$x='a,"a,b","""a""","""a, b, and c"""';
while( $x =~ s/^([^,"]*|"(""|[^"])*"),// ) {
  $_ = $1;
  s/^"(.*)"$/$1/;
  s/""/"/g;
  print "$_\n";
}
$x =~ s/^"(.*)"$/$1/;
$x =~ s/""/"/g;
print "$x\n";
こんなのどうでしょう

K's K 1999/08/12(木) 01:05:06
Auraiさん、ありがとうございます。目的のデータ517行分うまく切り出せました。
しかしPerlってすごいですね。バッチファイルぐらいしか知らない私でも根幹部分を教えてもらえれば、CSVからHTMLのテーブルに変換するプログラムが作れてしまう。あ、もちろん参考にするプログラムがあったからできたことですが・・・。
感動というかあきれています。
なお、桐の「テキストで書き出す」データはExcelのCSVと微妙に違っていました。
私と同じように桐のデータを利用する方は、一旦Excelを通して下さい。
Excelなんか持っていないという人もいらっしゃるでしょうね。
a"b"cというデータを桐はa"b"c、Excelは"a""b""c"に変換します。
ありがとうございました。

[上に] [前に] [次に]