Google Groups no longer supports new Usenet posts or subscriptions. Historical content remains viewable.
Dismiss

値がカンマを含むCSVファイル

2,499 views
Skip to first unread message

soumi

unread,
Jul 25, 2001, 1:11:04 PM7/25/01
to
こんにちわ。

先日は、最後の行の判別について教えていただきお世話になりました。
すべての行を覚えておき、最後に処理をするという手法で、件の問題と
は別の問題も片付きとても助かりました。

ところで、CSVファイルをインプットとして処理しているのですが、
CSVファイルにカンマを含む値があり対応に困っています。
AB,BC,"CD,DE",EF
というふうに、ダブルクォートされている"CD,DE"が該当する値です。
このファイルはもともとエクセルからCSVファイルで書き出したファイル
なのですが、一つのセルの中に CD,DE という値があったためにこうなった
と思われます。

きちんと前後がダブルクォートされているので何とかなりそうなのですが、
FSを正規表現にしてみたりしたのですがうまくいきません。

このようなケースで、どんな解決が考えられるでしょうか。
ご教授お願いします。

--
soumi

NIDE Naoyuki

unread,
Jul 25, 2001, 9:14:28 PM7/25/01
to
In article <3B5EFDA8...@tkd.att.ne.jp>,
es11...@tkd.att.ne.jp writes:
> ところで、CSVファイルをインプットとして処理しているのですが、
> CSVファイルにカンマを含む値があり対応に困っています。

ftp://ftp.ics.nara-wu.ac.jp/pub/nide/dosutil/uxtl412e.tgz で配布してい
るソフトの中に、CSVファイルを単一文字区切りのファイルに変換するcsvconvと
いうユーティリティがあり、これがawkで書かれていますので、参考になさって
はいかがでしょうか。中にcsvsplitという関数があって、これがCSVファイルの1
行を配列に分解するようになっています。

# 但しIEではアクセスできないと思います…あらかじめおことわり

ni...@ics.nara-wu.ac.jp

Shinji KONO

unread,
Jul 25, 2001, 9:33:19 PM7/25/01
to
河野 真治@琉球大情報工学です。

In article <3B5EFDA8...@tkd.att.ne.jp>,
soumi <es11...@tkd.att.ne.jp> writes
>CSVファイルにカンマを含む値があり対応に困っています。
>AB,BC,"CD,DE",EF

lex とか C で簡単なプログラムを書いて、
AB<tab>BC<tab>CD,DE<tab>EF
みたいに変換して対処しました。

もちろん、Perl/Awk でも書けるんですが、ちょっと遅いですね。

---
Shinji KONO @ Information Engineering, University of the Ryukyus,
PRESTO, Japan Science and Technology Corporation
河野真治 @ 琉球大学工学部情報工学科,
科学技術振興事業団さきがけ研究21(機能と構成)

Masaaki Sakano

unread,
Jul 26, 2001, 12:49:02 PM7/26/01
to
○fj.comp.lang.ruby にもクロスポスト (Followup-To の指定なし)

○fj.comp.lang.awk <3B5EFDA8...@tkd.att.ne.jp>の記事において
es11...@tkd.att.ne.jpさんは書かはりました。
> ところで、CSVファイルをインプットとして処理しているのですが、
> CSVファイルにカンマを含む値があり対応に困っています。

> このようなケースで、どんな解決が考えられるでしょうか。

「オブジェクト指向スクリプト言語 Ruby」
(まつもとゆきひろ/石塚圭樹共著; アスキー; ISBN4-7561-3254-5)
の第3.1章に、(Rubyによる)CSV形式の取り扱いについて 4通りの方法が
解説されています。少なくともアルゴリズムは参考になるかと思います。

さかのまさあき

Tomohiko Sakamoto

unread,
Jul 26, 2001, 9:43:53 PM7/26/01
to
In article <3B5EFDA8...@tkd.att.ne.jp>,

soumi <es11...@tkd.att.ne.jp> writes:
> CSVファイルにカンマを含む値があり対応に困っています。
> AB,BC,"CD,DE",EF
> というふうに、ダブルクォートされている"CD,DE"が該当する値です。
:
> きちんと前後がダブルクォートされているので何とかなりそうなのですが、

きちんと前後がダブルクォートされているのなら、こんなのでどうでしょう。

{
rec = $0
for (n = 1; ; n++) {
if (rec ~ /^"/) {
rec = substr(rec, 2)
pos = index(rec, "\"")
fld[n] = substr(rec, 1, pos-1)
rec = substr(rec, pos+2)
} else if (pos = index(rec, ",")) {
fld[n] = substr(rec, 1, pos-1)
rec = substr(rec, pos+1)
} else {
fld[n] = rec
break
}
}
for (i = 1; i <= n; i++)
printf "%d: %s\n", i, fld[i]
}

--
坂本智彦 saka...@sm.sony.co.jp

Tomohiko Sakamoto

unread,
Jul 26, 2001, 10:04:32 PM7/26/01
to
In article <9jqh0p$qqp$1...@itcnews.itc.sony.co.jp>,
saka...@sm.sony.co.jp (Tomohiko Sakamoto) writes:
> きちんと前後がダブルクォートされているのなら、こんなのでどうでしょう。

訂正します。行がダブルクォートで終わっている場合の処理が抜けていました。

{
rec = $0
for (n = 1; ; n++) {
if (rec ~ /^"/) {
rec = substr(rec, 2)
pos = index(rec, "\"")

$n = substr(rec, 1, pos-1)
rec = substr(rec, pos+2)
if (rec == "") break


} else if (pos = index(rec, ",")) {

$n = substr(rec, 1, pos-1)


rec = substr(rec, pos+1)
} else {

$n = rec


break
}
}
for (i = 1; i <= n; i++)

printf "%d: %s\n", i, $i
}

--
坂本智彦 saka...@sm.sony.co.jp

soumi

unread,
Aug 4, 2001, 11:34:46 PM8/4/01
to
こんにちわ。
返事が遅れまして失礼いたしました。
フォローしてくださった皆様ありがとうございました。

NIDE Naoyuki wrote:
>
> ftp://ftp.ics.nara-wu.ac.jp/pub/nide/dosutil/uxtl412e.tgz で配布してい
> るソフトの中に、CSVファイルを単一文字区切りのファイルに変換するcsvconvと
> いうユーティリティがあり、これがawkで書かれていますので、参考になさって
> はいかがでしょうか。中にcsvsplitという関数があって、これがCSVファイルの1

拝見いたしました。が、恥ずかしいですが私にはちょっと難解で・・・
でも参考にさせていただきます。

Shinji KONO wrote:
>
> lex とか C で簡単なプログラムを書いて、
> AB<tab>BC<tab>CD,DE<tab>EF
> みたいに変換して対処しました。
>
> もちろん、Perl/Awk でも書けるんですが、ちょっと遅いですね。

遅くなるのはぜんぜん問題ではないです。それよりすべてawkで処理したいと
考えましたので。

Masaaki Sakano wrote:
>
> 「オブジェクト指向スクリプト言語 Ruby」
> (まつもとゆきひろ/石塚圭樹共著; アスキー; ISBN4-7561-3254-5)
> の第3.1章に、(Rubyによる)CSV形式の取り扱いについて 4通りの方法が
> 解説されています。少なくともアルゴリズムは参考になるかと思います。

早速手配いたしました。が、今回には間に合いませんでしたので、今後
勉強させていただきます。

Tomohiko Sakamoto wrote:
>
> {
> rec = $0
> for (n = 1; ; n++) {
> if (rec ~ /^"/) {
> rec = substr(rec, 2)
> pos = index(rec, "\"")
> $n = substr(rec, 1, pos-1)
> rec = substr(rec, pos+2)
> if (rec == "") break
> } else if (pos = index(rec, ",")) {
> $n = substr(rec, 1, pos-1)
> rec = substr(rec, pos+1)
> } else {
> $n = rec
> break
> }
> }
> for (i = 1; i <= n; i++)
> printf "%d: %s\n", i, $i
> }

このコードを使うことで解決いたしました。とても勉強になりました。
最後の部分は以下のように変更して | でセパレートされるファイルに
して残りの処理を続けるようにしました。

for (i = 1; i <= n; i++)

printf "%s|", $i
printf "\n"


続けて二度も助けていただきまして感謝しております。
今後はもっと勉強いたします。
ありがとうございました。

--
soumi

Tomohiko Sakamoto

unread,
Aug 5, 2001, 6:46:05 AM8/5/01
to
In article <3B6CBED6...@tkd.att.ne.jp>,
soumi <es11...@tkd.att.ne.jp> writes:
> このコードを使うことで解決いたしました。とても勉強になりました。

そのコードには、まだ不十分なところがあります。

・空行の場合、 n = 1 になる。

・Excel が、a"b や "xyx" というフィールドを、"a""b" や """xyz""" と
いう形で CSVファイルにしることに対応していない。

そこで、次のようなコードをでっち上げました。
あんまり綺麗でなくて申し訳ありません。

{
if ($0 == "")
n = 0
else {


rec = $0
for (n = 1; ; n++) {
if (rec ~ /^"/) {

$n = ""
rec = substr(rec, 2)
for (;;) {
pos = index(rec, "\"")
if (pos == 0) {
$n = $n rec
rec = ""
break
}
if (substr(rec, pos+1, 1) != "\"") {
$n = $n substr(rec, 1, pos-1)
rec = substr(rec, pos+2)
break
}
$n = $n substr(rec, 1, pos)


rec = substr(rec, pos+2)
}
if (rec == "") break
} else if (pos = index(rec, ",")) {
$n = substr(rec, 1, pos-1)
rec = substr(rec, pos+1)
} else {
$n = rec
break
}
}
}
}

{
if (n > 0) {
for (i = 1; i < n; i++)
printf "%s|", $i
print $n
}
}

--
坂本智彦 saka...@sm.sony.co.jp

soumi

unread,
Aug 7, 2001, 1:45:48 PM8/7/01
to
こんにちわ。
さらにフォローがついていると思っていなかったので反応が遅れました。
失礼いたしました。

Tomohiko Sakamoto wrote:
>
> そのコードには、まだ不十分なところがあります。
>
> ・空行の場合、 n = 1 になる。
>
> ・Excel が、a"b や "xyx" というフィールドを、"a""b" や """xyz""" と
> いう形で CSVファイルにしることに対応していない。
>
> そこで、次のようなコードをでっち上げました。

恐れ入ります。
幸い、前者については、空行を作らない、後者については、イレギュラーな
記述は避ける、ということにして Excel 担当者に注意を払っていただき回避
することができました。
せっかく補足していただいたのですが、使わなくて済みそうです。
でもコードは保存して勉強させていただきます。
ありがとうございました。

--
soumi

0 new messages