- 締切済み
awkで項目番号ごとに行を列に並べる
[入力ファイル] a 10 1 b 10 2 c 10 3 d 10 4 a 20 5 b 20 6 c 20 7 d 20 8 a 30 9 b 30 0 c 30 1 d 30 2 を、2列目の項目番号を行、1列目の記号を列として (エクセルのピボットテーブルのようなイメージです) 以下のように並べ替えたいのです。 [出力ファイル] No. a b c d 10 1 2 3 4 20 5 6 7 8 30 9 0 1 2 これをawkスクリプトで書きたいのですが、 どのように書けばよいでしょうか? ※下記2点は希望ですが、難しければ非対応でも大丈夫です。 ・入力ファイルの1行目は一応abcdの順番にきれいに並んでいるものですが 順番がabdcなどとずれていても処理できるスクリプトにしたいです。 ・出力後のabcdの列順序は、スクリプトを修正することで 自由に変更できるとさらに助かります。 教えてください。 よろしくお願いいたします。
- みんなの回答 (4)
- 専門家の回答
みんなの回答
- ysawave
- ベストアンサー率50% (2/4)
作ってみました。 どうでしょうか? ----- # a b c d の列順序を決める BEGIN{ item=split("b a d c", idx); } # 2列目の項目番号を行、1列目の記号を列としてtbl[]格納 { tbl[$2,$1]=$3; if(!($2 in list)) name[(list[$2]=++cnt)]=$2; } # tbl[]を表示 END{ printf("No."); for(i=1; i<=item; ++i) printf(" %2s", idx[i]); print ""; for(n=1; n<=cnt; ++n){ printf("%3s", name[n]); for(i=1; i<=item; ++i) printf(" %2s", tbl[name[n],idx[i]]); print ""; } } -----
- ktsykh
- ベストアンサー率0% (0/0)
これでどうでしょう。 BEGIN { n1 = "a"; n2 = "b"; n3= "c"; n4 = "d" FS = "[ ]+" OFS = "\t" } $1 ~ n1 { a[n1][$2] = $3 } $1 ~ n2 { a[n2][$2] = $3 } $1 ~ n3 { a[n3][$2] = $3 } $1 ~ n4 { a[n4][$2] = $3 } END { print "No.", n1, n2, n3, n4 print "10", a[n1][10], a[n2][10], a[n3][10], a[n4][10] print "20", a[n1][20], a[n2][20], a[n3][20], a[n4][20] print "30", a[n1][30], a[n2][30], a[n3][30], a[n4][30] } BEGIN の中で表示する際の abcd の順序を指定できます。
- trapezium
- ベストアンサー率62% (276/442)
awk -v order="index.txt" 'BEGIN{for (n=1;getline a[n]<order;n++);} {b[$2]=1;c[$1,$2]=$3} END{printf "No."; for (j=1;j<n;j++) printf "%3s",a[j]; print ""; for (i in b) {printf "%-3d",i; for (j=1;j<n;j++) printf "%3d",c[a[j],i]; print ""}}' input.txt No. b a d c 10 2 1 4 3 20 6 5 8 7 30 0 9 2 1 ワンライナーで見難いかもですが、表示順は -v order でファイル指定するようしてみました index.txt は単に1行ひとつづつ書くだけ。 b a d c 上記の場合こんなかんじ。 あとデリミタの全角空白は普通の半角空白に置き換えました。
- osamuy
- ベストアンサー率42% (1231/2878)
書いてみた感じ、awkを選択するのは良くないような気がします。保守性の観点から。
- 参考URL:
- http://ideone.com/cbVAj
お礼
早速のご回答ありがとうございます。 作っていただいたスクリプトを見させてもらいました。 希望通りの出力が可能になりました。 しかし、おっしゃる通り、だいぶ複雑なので、保守の観点から採用させてもらうか悩むところです。もう少し悩んでみます。 とはいえ、こんな複雑なスクリプトを作ってくださり、ありがとうございました。
お礼
ご回答ありがとうございます。 ワンライナーの扱いがまだ苦手で、解読に時間がかかってしまいました。 v orderという方法もあるのですね。まだまだ知らないことが多いです。 都合上、外部ファイルの使用は避けたかったので、a,b,c,d列を各々抜き出したtmpファイル4つを一時的に作り、getlineを使って好みの順番で列のファイル結合する方法を採択することにしました。これでひとまずやりたいことは解決しました。 ご提案いただいた方法と全然関係なくてすみません。汗。 例[a.txt] No.とaの2列のテキストファイル それをb,c,dの分も作る。 begin{print ("No.","a","b","c","d")} { getline<a.txt A=$2 getline<b.txt B=$2 getline<c.txt C=$2 getline<d.txt D=$2 print($1,A,B,C,D) }