Linuxコンソール上で、Excelのように行と列を入れ替えたい時がある。
そんなときは、以下のようにawkなどを使うことで実現可能だ。
1.awkを使う
まずはawkを使う場合。
以下のようにすることで、行と列の入れ替えが可能だ。
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
[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のワンライナーで入れ替えを行うこともできる。
cat ファイルPATH | perl -anF'\t|\n' -e'$n=@F-1if!$n;for(0..$n){push@{$$m[$_]},$F[$_]}''END{print map{join"\t",@$_,"\n"}@$m}'
[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のワンライナーでも、行と列の入れ替えが行える。
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()))))"
[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のワンライナーでも、表の行列入れ替えを行える。
cat /tmp/test1_1.txt | ruby -e'puts readlines.map(&:split).transpose.map{|x|x*" "}'
[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コマンドを使うことで、表の行列入れ替えが簡単に行える。
なお、区切り文字がデフォルトではタブになってる点は注意が必要。
datamash transpose < ファイルPATH
[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というコマンドを使うことでも、表の行列入れ替えを行える。
まず以下のコマンドでまずインストールをする。
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
で、行列の反転は以下。
transpose -t ファイルPATH
[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では最初から使える)。
sudo apt-get install rs
pasteのようにも使えるので、だいぶ便利だ。
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
いくつか方法はあるので、環境や状況に合わせて使い分けていきたい。