先日は、最後の行の判別について教えていただきお世話になりました。
すべての行を覚えておき、最後に処理をするという手法で、件の問題と
は別の問題も片付きとても助かりました。
ところで、CSVファイルをインプットとして処理しているのですが、
CSVファイルにカンマを含む値があり対応に困っています。
AB,BC,"CD,DE",EF
というふうに、ダブルクォートされている"CD,DE"が該当する値です。
このファイルはもともとエクセルからCSVファイルで書き出したファイル
なのですが、一つのセルの中に CD,DE という値があったためにこうなった
と思われます。
きちんと前後がダブルクォートされているので何とかなりそうなのですが、
FSを正規表現にしてみたりしたのですがうまくいきません。
このようなケースで、どんな解決が考えられるでしょうか。
ご教授お願いします。
--
soumi
ftp://ftp.ics.nara-wu.ac.jp/pub/nide/dosutil/uxtl412e.tgz で配布してい
るソフトの中に、CSVファイルを単一文字区切りのファイルに変換するcsvconvと
いうユーティリティがあり、これがawkで書かれていますので、参考になさって
はいかがでしょうか。中にcsvsplitという関数があって、これがCSVファイルの1
行を配列に分解するようになっています。
# 但しIEではアクセスできないと思います…あらかじめおことわり
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(機能と構成)
○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通りの方法が
解説されています。少なくともアルゴリズムは参考になるかと思います。
さかのまさあき
きちんと前後がダブルクォートされているのなら、こんなのでどうでしょう。
{
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
訂正します。行がダブルクォートで終わっている場合の処理が抜けていました。
{
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
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
そのコードには、まだ不十分なところがあります。
・空行の場合、 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
Tomohiko Sakamoto wrote:
>
> そのコードには、まだ不十分なところがあります。
>
> ・空行の場合、 n = 1 になる。
>
> ・Excel が、a"b や "xyx" というフィールドを、"a""b" や """xyz""" と
> いう形で CSVファイルにしることに対応していない。
>
> そこで、次のようなコードをでっち上げました。
恐れ入ります。
幸い、前者については、空行を作らない、後者については、イレギュラーな
記述は避ける、ということにして Excel 担当者に注意を払っていただき回避
することができました。
せっかく補足していただいたのですが、使わなくて済みそうです。
でもコードは保存して勉強させていただきます。
ありがとうございました。
--
soumi