- 締切済み
データをブロックごとに並べ替えるスクリプト
データをブロックごとに移動して並べ替えたいのですが、 うまくいくスクリプトが書けず困っています。 APR_A----- abc 1 def 2 APR_B----- abc 3 def 4 APR_C----- abc 5 def 6 APR_A----- ghi 1 jkl 2 mno 3 APR_B----- ghi 4 jkl 5 mno 6 APR_C----- ghi 7 jkl 8 mno 9 のようなフォーマットのデータがあります。 これを以下のようにフォーマットを変えたいのですが、 awkを使ってどのようにスクリプトを書いたらよいでしょうか。 元データの中で、区切りの行は常にAPR_で始まっています。 APR_で始まる行に来たら次の列に移って2列目のみprint というのを繰り返し、APR_Aに戻ってきたら、 1列目(abc,defなど)、2列目ともprintして同様に繰り返す。 各ブロックの行数はまちまちです。(最初のブロックのように2行のブロックもあれば2番目のブロックのように3行のもあります) rowtitle APR_A APR_B APR_C abc 1 3 5 def 2 4 6 ghi 1 4 7 jkl 2 5 8 mno 3 6 9 分かりにくい文章ですが、理解していただけることを願っています。 よろしくお願いします。
- みんなの回答 (2)
- 専門家の回答
みんなの回答
- ryonana
- ベストアンサー率0% (0/3)
簡単ではなさそうですね。 そうした場合は、一本のスクリプトでも可能ですが、複雑になるので 後々のメンテを考慮すればいくつかの機能で分けて対応した方が 良いと思います。 最終的な正解まではお手伝いできませんが 前回のスクリプトを修正して以下のような形にしたら いかがでしょうか? まずはソートする情報のネタを作ってあげて それをソートしてみてください。 後は帳票出力編集の要領で目的の物を出力すれぱと思います。 ある程度の知識はある方と思いますのでここから先はがんばってください。 【sum1.awk】 ---------------------------------------------------------------- #!/usr/bin/awk -f { if($1 ~ /APR_.*----/) { # カラムタイトル myClm=$1 # カラムタイトル gsub("-","",myClm) # "----" を除く if ( tblClm[myClm] == "" ) { idxClm++ tblClm[myClm] = idxClm tblClmIdx[idxClm] = myClm } } else { # 行タイトルとデータを取得 myRow=$1 # 行タイトル tblRow[myClm,myRow] ++ idxRow=tblRow[myClm,myRow] idxOut++ tblOut[idxOut] =sprintf("%d\t%s\t%s\t%d",idxRow,myRow,myClm,$2) } } END { # カラムタイトル情報 for(i=1;i<=idxClm;i++) { print "0\t" tblClmIdx[i] } # データ for(i=1;i<=idxOut;i++) { print tblOut[i] } } ---------------------------------------------------------------- % awk -f sum1.awk sum.dat > sum1.tmp % sort sum1.tmp -t \t > sum1.srt
- ryonana
- ベストアンサー率0% (0/3)
どういった環境かわからないので動作保証はありませんが。。。 まず、データを読み込んで連想配列に格納していきます。 それから読み終えた段階で後処理「END」の中で 配列に溜め込んだ情報を出力して行きます。 連想配列を使用しているので要望の回答とは順序が 異なりますが結果は得られると思います。 もし同様の値にしたい場合は添字配列で利用して 既に追加されている項目を考慮などすれば可能です。 【以下サンプル】 ※インデントは自分でそろえてください。 #!/usr/bin/awk -f # BEGIN { } { if($1 ~ /APR_.*----/) { # カラムタイトル myClm=$1 gsub("-","",myClm) tblClmNm[myClm]=1 } else { # 行タイトルとデータを取得 myRow=$1 tblVal[myClm,myRow]=$2 tblRowNm[myRow]=1 } } END { # カラムタイトル for(myClm in tblClmNm) { printf myClm "\t" } printf "\n" # データを標準出力 for(myRow in tblRowNm) { printf myRow for(myClm in tblClmNm) { printf "\t" tblVal[myClm,myRow] } printf "\n" } }
補足
ありがとうございます。発想の転換で勉強になります。 ただ例に挙げたデータではうまくいきましたが、 実際のデータではmyRowに相当する値が複数回出てきます。 連想配列を使うとそれらの行は上書きされてしまいますよね。 つまり以下のようなデータの場合、 APR_A----- abc 1 def 2 APR_B----- abc 3 def 4 APR_C----- abc 5 def 6 APR_A----- ghi 1 jkl 2 mno 3 APR_B----- ghi 4 jkl 5 mno 6 APR_C----- ghi 7 jkl 8 mno 9 APR_A----- abc 1 def 2 ghi 3 APR_B----- abc 4 def 5 ghi 6 APR_C----- abc 7 def 8 ghi 9 このようにしたい: APR_A APR_B APR_C abc 1 3 5 def 2 4 6 ghi 1 4 7 jkl 2 5 8 mno 3 6 9 abc 1 4 7 def 2 5 8 ghi 3 6 9 のですが、このようになってしまいます: APR_A APR_B APR_C def 2 5 8 jkl 2 5 8 abc 1 4 7 ghi 3 6 9 mno 3 6 9 つまりabcの行、defの行、ghiの行が上書きされてしまいます。 こうならないようにする方法はありますでしょうか。