• 締切済み

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の列順序は、スクリプトを修正することで   自由に変更できるとさらに助かります。 教えてください。 よろしくお願いいたします。

  • wiket
  • お礼率60% (3/5)

みんなの回答

  • ysawave
  • ベストアンサー率50% (2/4)
回答No.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)
回答No.3

これでどうでしょう。 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)
回答No.2

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 上記の場合こんなかんじ。 あとデリミタの全角空白は普通の半角空白に置き換えました。

wiket
質問者

お礼

ご回答ありがとうございます。 ワンライナーの扱いがまだ苦手で、解読に時間がかかってしまいました。 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) }

  • osamuy
  • ベストアンサー率42% (1231/2878)
回答No.1

書いてみた感じ、awkを選択するのは良くないような気がします。保守性の観点から。

参考URL:
http://ideone.com/cbVAj
wiket
質問者

お礼

早速のご回答ありがとうございます。 作っていただいたスクリプトを見させてもらいました。 希望通りの出力が可能になりました。 しかし、おっしゃる通り、だいぶ複雑なので、保守の観点から採用させてもらうか悩むところです。もう少し悩んでみます。 とはいえ、こんな複雑なスクリプトを作ってくださり、ありがとうございました。

関連するQ&A

  • Awkで固定行ずつ行列転置

    A B C D E F G H . . . と、1列にデータが並んだテキストファイルの中身を A B C D E F G H ... のように4列ずつに区切って並べ替えるawkスクリプトを 書きたいのですが、どのように書けばいいでしょうか? もとのデータの行数は4の倍数とは限らないので、 並べ替え後の最後の行はフィールドが4つ未満になるかもしれません。

  • awkを使って文字列処理の問題

    awkで以下のことをやりたいですが、 a.txtの中身は aaaa bbbb cccc の三つのレコードがあります。 b.txtの中身は 東京a 埼玉b 千葉c 東京d になってます。 ファイルa.txtのみっつのレコードのを読み込んできて、b.txtに対して検索して、東京 という文字列があれば、そのレコードは、aaaaに置き換えて、あるファイルに出力する ようなスクリプトを書きたいです。 どう書けば、いいですか?教えていただけませんか?

  • エクセルの行と列の項目を入れ替えたいのですが

    大きな表を作成しているのですが、行(1、2、3・・)と列(A,B,C,D・・・)を入れかえる必要がでてきました。すなわち、行を現在の列である(A,B,C,D・・・)とし、列を現在の行である(1、2、3、・・・)にしたいのです。こつこつデータを打ち直すしか方法はないのでしょうか?どなたか教えてください。お願い致します。

  • ある列をキーにして、複数行を1列で出力したい

    AWKで、以下の処理をしたいです。 ・1列目をキーにしたテーブルを作る ・1列目共通で2列目が複数ある場合は、並べて記載したい。 どなたか、スクリプト案お願いします。 例 Input file A あ B あ B い C い Output file A あ B あ/い C い

  • awkで二つのファイルを比較し出力する方法

    UNIXで二つのファイルを使って別ファイルを出力する 処理をしたいのですが、awkで二つのファイルを扱う方法 が分かりませんでした。 やりたい処理は以下のような事です。 ファイルAの1行目"AAA B"と同じ行がファイルBにあったら、ファイルAの"AAA B"の次の行に、 ファイルBの次の行"YYY bbb"を挟み込みます。 もし、ファイルBに同じ行がなかったら、 ファイルAの次の行に"NG"を挟み込みます。 [ファイルA] AAA B ZZZ B AAA C ZZZ C AAA D ZZZ D [ファイルB] AAA B YYY bbb AAA C YYY bbb [出力ファイル] AAA B YYY bbb ZZZ B AAA C YYY ccc ZZZ C AAA D NG どなたか良いスクリプトありましたら 教えていただけないでしょうか。 よろしくお願いします。

  • SQLでの複数列が重複してる行の削除(SQLite)

    こんにちは。 複数の列で重複した列がある場合の行削除のクエリが思い付きません。 A表 A    B   C   D   ==== === === ==== 1 ああああ 100 200 ABCD 2 いいいい 200  90 ASKB 3 うううう 300 800 ALTE 4 ええええ 400 200 ABCD B表   ==== === === ==== 1 ああああ 100 200 ABCD 2 ああああ 400 100 ABCD このとき、A表とB表を比較し、B,C,D列で重複したデータをB表から削除した行を表示したいのです。 ほしいデータは B表   ==== === === ==== 2 ああああ 400 100 ABCD です。よろしくお願いします。

  • awkで列を集計するシェルについて

    シェル初心者です。教えてください。 ログファイルが10万行超えるものでシェルにて集計することになり、下記のような集計ができればと思っています。 商店名 商品名  価格 A商店 りんご   100 B商店  ぶどう 300 A商店  みかん 150 C商店  りんご 100 A商店  りんご 100 B商店  みかん 150 C商店  りんご 100 C商店  ぶどう 300 ※各列はブランク(空白)によって区切られ、改行済みで行数は10万行以上 (1)awk '{print $1}' | uniq -d (重複した商店の抽出) (2)awk '{print $2}' | uniq -d (重複した商品名の抽出) (1)、(2)の抽出を満たす「価格」の合計を"集計結果”として > shukei.txt などに出力したいと思ってます。 VBAでいれば、firlterしsumifして合計するようなイメージのものです。 ご教授お願い致します><

  • awkで複数ファイルのある列を抽出し出力したい

    awkプログラミングの初心者です。 今、複数ファイル(1000ファイル)から、それぞれある列(すべて同じ列番号)のデータを抜き出して、1つのファイルに出力したいと考えています。 具体的には、1列目に共通項、2列目以降に1000ファイル分の抽出された列を、合計1001列となるような1つのファイルとして出力したいと考えております。 awkを使って出力するには、どのようなスクリプトを作ればよいか教えていただけませんでしょうか。 <イメージ> 元となるファイル(例えば下記のように3ファイル、実際には1000ファイル)があります。 file1.txt: 1  10 2  15 3  17 :  : 1000  25 file2.txt: 1  5 2  40 3  22 :  : 1000  17 file3.txt: 1  9 2  20 3  16 :  : 1000  32 出力後のファイルイメージ: 1  10  5  9 2  15  40  20 3  17  22  16 :  :  :  : 1000  25  17  32 ちなみに、自分で作成したawkスクリプト(下記)では、上記出力後のイメージとは異なり、 縦にデータが結合されてしまいました。 awk `{print $2}` ./file*.txt > Output.txt 出力後のファイル: 10 15 17 : 25 5 40 :

  • 行と列を入れ替えた式

    行と列を入れ替えた式 A=(a b c d)とします。この行列の行と列を入れ替えた行列は(a c b d)らしいんですが、行と列を入れ替えるという意味がよくわかりません 僕は、1行目と1列目を換えて、2行目と2列目を換えると考えました。しかし、その場合は(a b c d)で元に戻ってしまします。 何故、僕の考えでは行と列を入れ替えた行列にならないんでしょうか?? 誰か、うまく教えらる人 アドバイスおねがいします

  • エクセルの行にあるものを列にする数式

    エクセルの数式を使って、行に入っているものを別のシートの列に入力することについて質問です。 例(シートA)    A  B  C  D 1  月 火 水 木 2  10 20 30 40 ABCDが列番号、1,2が行番号です。 このように入力したシートがあります。 そして、違うシートには下のように入力したいのです。 例(シートB)    A  B  C  D 1  月 10 2  火 20  3  水 30 4 木 40 (ずれてしまってすみません) シートBの『10,20,30,40』のところに数式を入れたいのですが、シートAに入力した時に、シートBにそのまま反映されるようにしたいのです。 ちなみに、シートBのB1(10となっているところ)に『=シートA!A2』と入力して、それをシートBのB列全体にコピーすると、シートAのA列部分を縦によんでしまうので、反映されません。 シートAでは横によんでいって、それをシートBでは縦に表示する、というところです。 このような説明でわかりましたでしょうか? $マークも使って絶対値もやりましたが、それでもダメでした。 いい方法をご存知のかた、よろしくお願いいたします。

専門家に質問してみよう