• ベストアンサー

テキスト編集

csvファイルの編集について質問です。 例えば下記のような先頭のKEY部分が重複していて、その後ろにカンマ区切りのデータがあります。 aaa,りんご,123 aaa,みかん1,456 aaa,いちご2,789 bb,データ1,098 bb,データ3,028 bb,データ2,198 cccc,ライオン,555 cccc,象,634 これを以下のように 重複しているKEYのデータを一つにまとめたいのですがなにかいい案はないでしょうか? aaa,りんご,123,みかん,456,いちご,789 bb,データ1,098,データ3,028,データ2,198 cccc,ライオン,555,象,634 UNIXで作業しているのでAWKなどのUNIXコマンドでなんとか 編集したいのですが教えてください。宜しくお願いします。

質問者が選んだベストアンサー

  • ベストアンサー
  • iriyak
  • ベストアンサー率48% (40/82)
回答No.5

こんにちは。 全部回答してしまっては質問者の楽しみを奪ってしまうことになりますので :) 用語の一部を簡単にメモしておきます。読解にトライください。 また、参考書籍が記載された類似 QNo. を参考URLに残しています。ご参考まで。 > { for (i = 2; i <= NF; i++) > 2フィールド以降のフィールドの数だけループさせる? そうです。NF (Number of Fields) は区切子 FS (Field Separator) で区切られたデータ(フィールド)の個数を示します。 > { Arr[$1] = Arr[$1] OFS $i } > 出力フィールドの区切り文字を指定している??(わかりません) Arr[$1] は、$1 をキーに設定した連想配列 (Association Array) Arr の値は、を意味します。Arr[$1] OFS $i は文字列の連接 (Concatenation) です。Arr[$1], OFS, $i を繋げた結果を Arr[$1] に代入せよ、という意です。OFS は、出力時のフィールド区別子 (Field Separator) です。$i は、i 番目のフィールドです。 ※ $i は i が 3 の場合は $3 と同じ意味です。$(i) と表現しても可。また $() カッコ内に式を書くことも可。$(NF) や $(i + 1) など。 > END { for (i in Arr) { print i Arr[i] }}' > 最後に標準出力をしている?(forのところはわかりません) 連想配列 Arr に登録されている任意のキー i について print i Arr[i] を実行せよ、という意味です。先程の代入文でキーにはレコードの $1 が登録されていますから、それ毎に、という意味になります。 この One-liner の肝は、連想配列 Arr です。そして Awk の One-liner でこの連想配列を利用するシーンが非常に多いです。今回を機に連想配列をマスターし、日常で活用ください! (参考OKWave QNo) QNo.4138535『複数のテキストから同じ行数の文字列を抽出し,別のテキストに出力する方法』

参考URL:
http://okwave.jp/qa4138535.html
kariyu1231
質問者

お礼

詳しく有難うございました。仕事の幅が広がり、感謝しています。 本当に有難うございました。

その他の回答 (4)

  • sakusaker7
  • ベストアンサー率62% (800/1280)
回答No.4

#2です。 訂正。 awk -F, '{r[$i] = FS r[$2] FS r[$3]}; END{for (i in r) print i, r[i]}' ↓ awk -F, '{r[$1] = r[$1] FS $2 FS $3}; END{for (i in r) print i, r[i]}' これに質問にあるデータを喰わせると cccc ,ライオン,555,象,634 bb ,データ1,098,データ3,028,データ2,198 aaa ,りんご,123,みかん1,456,いちご2,789 こうなりました。 使うawkによっては順番が違うこともあるでしょう。

kariyu1231
質問者

お礼

有難うございます。色々な記述方法があるのですね!勉強になりました。 でも未だに皆さんの書かれたAWKが何をしているのか解読できていません。 使いこなせるように勉強してみます。有難うございました。

  • iriyak
  • ベストアンサー率48% (40/82)
回答No.3

こんにちは。 $1 (KEY) の出現順と出力順は一致しなくてもいい、ということであれば、下記はいかがでしょう。sort -n はおまけです。出力順の変更は awk とは切り出してもいいのでは? というつもりで付け加えました。 zebra[Wed]$ cat sample.txt 10,16 10,9 1000,1095 1034,1066 1034,1221 400,109 400,99 400,20 zebra[Wed]$ awk 'BEGIN { FS = OFS = "," } { for (i = 2; i <= NF; i++) { Arr[$1] = Arr[$1] OFS $i }} END { for (i in Arr) { print i Arr[i] }}' sample.txt 400,109,99,20 10,16,9 1034,1066,1221 1000,1095 zebra[Wed]$ awk 'BEGIN { FS = OFS = "," } { for (i = 2; i <= NF; i++) { Arr[$1] = Arr[$1] OFS $i }} END { for (i in Arr) { print i Arr[i] }}' sample.txt | sort -n 10,16,9 400,109,99,20 1000,1095 1034,1066,1221 zebra[Wed]$

kariyu1231
質問者

お礼

有難うございました。ばっちり出来ました。AWKは使いこなせれば 最強のテキスト編集ツールですね!!!

kariyu1231
質問者

補足

このプログラムで上手く処理できましたがAWKがどのように動いているのかが 本で調べていますが全く理解できません。今後にも生かしたいので解説も付けてもらえないでしょうか?どうぞ宜しくお願いします。。。 awk 'BEGIN { FS = OFS = "," } { for (i = 2; i <= NF; i++) { Arr[$1] = Arr[$1] OFS $i }} END { for (i in Arr) { print i Arr[i] }}' sample.txt 【自分なりに】 'BEGIN { FS = OFS = "," } 初めにフィールドセパレータを","にしている。 { for (i = 2; i <= NF; i++) 2フィールド以降のフィールドの数だけループさせる? { Arr[$1] = Arr[$1] OFS $i } 出力フィールドの区切り文字を指定している??(わかりません) END { for (i in Arr) { print i Arr[i] }}' 最後に標準出力をしている?(forのところはわかりません) ※ぜひ解説お願いします。

  • sakusaker7
  • ベストアンサー率62% (800/1280)
回答No.2

awk -F, '{r[$i] = FS r[$2] FS r[$3]}; END{for (i in r) print i, r[i]}' こんなんとか。 キーの出現順は不定なので、sortするなりなんなりどうぞ。 #フィールドの数が増えたりしたらしらね ;-p

kariyu1231
質問者

補足

有難うございます。実行してみると・・・ <<Sample.txt>> 10,16 10,9 1000,1095 1034,1066 1034,1221 400,109 400,99 400,20 【コマンド】 awk -F, '{r[$i] = FS r[$2] FS r[$3]}; END{for (i in r) print i, r[i]}' Sample.txt 【結果】 16 109 1066 400,99 ,, 1095 9 99 400,20 ,, 1034,1221 ,, 1000,1095 ,, 10,16 ,, 400,109 ,, 20 1221 10,9 ,, 1034,1066 ,, 【理想】 10,16,9 1000,1095 1034,1066,1221 400,109,99,20 ※ちょっと希望の形にはならなかったのですが使い方が間違っていますか??

  • kumoz
  • ベストアンサー率64% (120/185)
回答No.1

AWK ではなく Perl ですが、次のような感じでできるのではないかと思います。試してみてください。 $ perl -ne 'chomp; ($key, $value) = split(/,/, $_, 2); push @{$hash{$key}}, $value; > END { print join(",", $_, @{$hash{$_}}), "\n" foreach sort keys %hash; }' csv_file

kariyu1231
質問者

お礼

有難うございます。Perlの場合だと、こんな風になるのですか!! 参考になります。AWKや他のUNIXコマンドでは、出来ないのでしょうか?

関連するQ&A