Linuxコンソール上で、Excelのように行と列を入れ替えたい時がある。
そんなときは、以下のようにawkなどを使うことで実現可能だ。

1.awkを使う

まずはawkを使う場合。
以下のようにすることで、行と列の入れ替えが可能だ。

bash
awk ' { for (i=1; i<=NF; i++) { a[NR,i] = $i } } NF>p { p = NF } END { for(j=1; j<=p; j++) { str=a[1,j]; for(i=2; i<=NR; i++){ str=str" "a[i,j]; } print str } }' 対象ファイルPATH
shell
[root@BS-PUB-CENT7-01 ~]# cat /tmp/test1_1.txt id name prefecture value 1 aaa 1 123 2 bbb 2 544 3 ccc 1 65745 4 ddd 1 122 5 eee 2 222 6 fff 1 444 7 ggg 3 566 8 hhh 4 111 9 iii 3 12 10 bbb 2 1243 11 ddd 1 4423 [root@BS-PUB-CENT7-01 ~]# awk ' > { for (i=1; i<=NF; i++) { a[NR,i] = $i } } > NF>p { p = NF } > END { > for(j=1; j<=p; j++) { str=a[1,j]; for(i=2; i<=NR; i++){ str=str" "a[i,j]; } > print str > } > }' /tmp/test1_1.txt id 1 2 3 4 5 6 7 8 9 10 11 name aaa bbb ccc ddd eee fff ggg hhh iii bbb ddd prefecture 1 2 1 1 2 1 3 4 3 2 1 value 123 544 65745 122 222 444 566 111 12 1243 4423

2.perlを使う

perlのワンライナーで入れ替えを行うこともできる。

bash
cat ファイルPATH | perl -anF'\t|\n' -e'$n=@F-1if!$n;for(0..$n){push@{$$m[$_]},$F[$_]}''END{print map{join"\t",@$_,"\n"}@$m}'
shell
[root@BS-PUB-CENT7-01 ~]# cat /tmp/test1_1.txt | perl -anF'\t|\n' -e'$n=@F-1if!$n;for(0..$n){push@{$$m[$_]},$F[$_]}''END{print map{join"\t",@$_,"\n"}@$m}' id 1 2 3 4 5 6 7 8 9 10 11 name aaa bbb ccc ddd eee fff ggg hhh iii bbb ddd prefecture 1 2 1 1 2 1 3 4 3 2 1 value 123 544 65745 122 222 444 566 111 12 1243 4423

3.pythonを使う

pythonのワンライナーでも、行と列の入れ替えが行える。

bash
cat ファイルPATH | python -c "import sys; print('\n'.join(' '.join(c) for c in zip(*(l.split() for l in sys.stdin.readlines() if l.strip()))))"
shell
[root@BS-PUB-CENT7-01 ~]# cat /tmp/test1_1.txt | python -c "import sys; print('\n'.join(' '.join(c) for c in zip(*(l.split() for l in sys.stdin.readlines() if l.strip()))))" id 1 2 3 4 5 6 7 8 9 10 11 name aaa bbb ccc ddd eee fff ggg hhh iii bbb ddd prefecture 1 2 1 1 2 1 3 4 3 2 1 value 123 544 65745 122 222 444 566 111 12 1243 4423

4.rubyを使う

rubyのワンライナーでも、表の行列入れ替えを行える。

bash
cat /tmp/test1_1.txt | ruby -e'puts readlines.map(&:split).transpose.map{|x|x*" "}'
shell
[root@BS-PUB-CENT7-01 src]# cat /tmp/test1_1.txt | ruby -e'puts readlines.map(&:split).transpose.map{|x|x*" "}' id 1 2 3 4 5 6 7 8 9 10 11 name aaa bbb ccc ddd eee fff ggg hhh iii bbb ddd prefecture 1 2 1 1 2 1 3 4 3 2 1 value 123 544 65745 122 222 444 566 111 12 1243 4423

5.datamashコマンドを使う

以前紹介したdatamashコマンドを使うことで、表の行列入れ替えが簡単に行える。
なお、区切り文字がデフォルトではタブになってる点は注意が必要。

bash
datamash transpose < ファイルPATH
shell
[root@BS-PUB-CENT7-01 ~]# cat /tmp/test1_1.txt | datamash transpose id 1 2 3 4 5 6 7 8 9 10 11 name aaa bbb ccc ddd eee fff ggg hhh iii bbb ddd prefecture 1 2 1 1 2 1 3 4 3 2 1 value 123 544 65745 122 222 444 566 111 12 1243 4423

6.transposeコマンドを使う

transposeというコマンドを使うことでも、表の行列入れ替えを行える。
まず以下のコマンドでまずインストールをする。

bash
wget http://downloads.sourceforge.net/project/transpose/transpose/transpose-2.0/2.0/transpose-2.0.zip unzip transpose-2.0.zip cd transpose-2.0/src gcc transpose.c -o /usr/bin/transpose

で、行列の反転は以下。

bash
transpose -t ファイルPATH
shell
[root@BS-PUB-CENT7-01 src]# transpose -t /tmp/test1_1.txt id 1 2 3 4 5 6 7 8 9 10 11 name aaa bbb ccc ddd eee fff ggg hhh iii bbb ddd prefecture 1 2 1 1 2 1 3 4 3 2 1 value 123 544 65745 122 222 444 566 111 12 1243 4423

7.rsコマンドを使う(2016/07/05 追記)

BSD系のコマンドであるrsコマンドで「-T」オプションを使うことで、行列変換が可能だ。
Ubuntuならば、以下のコマンドでインストールできる(Macでは最初から使える)。

bash
sudo apt-get install rs

pasteのようにも使えるので、だいぶ便利だ。

shell
blacknon@BS-PUB-UBUNTU-01:/tmp$ seq 50 | rs 0 10 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 blacknon@BS-PUB-UBUNTU-01:/tmp$ seq 50 | rs 0 10 | rs -T 1 11 21 31 41 2 12 22 32 42 3 13 23 33 43 4 14 24 34 44 5 15 25 35 45 6 16 26 36 46 7 17 27 37 47 8 18 28 38 48 9 19 29 39 49 10 20 30 40 50

いくつか方法はあるので、環境や状況に合わせて使い分けていきたい。