awkでフィールドの入れ替え


アニメ『うぽって!!』

左右逆から読むと意味が分かります。登場する女子たちは実は銃という、発想がぶっ飛んでいて面白いです。銃が銃を撃つのかああ。

今回はawkでフィールドを左右逆にしてみます。

まずは、元データを適当に作ります。

takk@deb9:~$ seq 0 255 | perl -ne 'print chr' | od -tx1 -Ax | head
000000 00 01 02 03 04 05 06 07 08 09 0a 0b 0c 0d 0e 0f
000010 10 11 12 13 14 15 16 17 18 19 1a 1b 1c 1d 1e 1f
000020 20 21 22 23 24 25 26 27 28 29 2a 2b 2c 2d 2e 2f
000030 30 31 32 33 34 35 36 37 38 39 3a 3b 3c 3d 3e 3f
000040 40 41 42 43 44 45 46 47 48 49 4a 4b 4c 4d 4e 4f
000050 50 51 52 53 54 55 56 57 58 59 5a 5b 5c 5d 5e 5f
000060 60 61 62 63 64 65 66 67 68 69 6a 6b 6c 6d 6e 6f
000070 70 71 72 73 74 75 76 77 78 79 7a 7b 7c 7d 7e 7f
000080 80 81 82 83 84 85 86 87 88 89 8a 8b 8c 8d 8e 8f
000090 90 91 92 93 94 95 96 97 98 99 9a 9b 9c 9d 9e 9f
takk@deb9:~$ 

このデータをawkが読み込むと、変数$1には、1列目のデータ(000000~000090)、
$2には、2列目のデータ(00~90)というように、$番号で、各フィールドの文字列にアクセスできます。$0は、一行まるまる格納されます。

$番号は、書き換え可能で、例えば、一番右(17列目)の16進を、10進にしたい場合は、

takk@deb9:~$ !! | awk '{$17=strtonum("0x"$17);print$0}'
seq 0 255 | perl -ne 'print chr' | od -tx1 -Ax | head | awk '{$17=strtonum("0x"$17);print$0}'
000000 00 01 02 03 04 05 06 07 08 09 0a 0b 0c 0d 0e 15
000010 10 11 12 13 14 15 16 17 18 19 1a 1b 1c 1d 1e 31
000020 20 21 22 23 24 25 26 27 28 29 2a 2b 2c 2d 2e 47
000030 30 31 32 33 34 35 36 37 38 39 3a 3b 3c 3d 3e 63
000040 40 41 42 43 44 45 46 47 48 49 4a 4b 4c 4d 4e 79
000050 50 51 52 53 54 55 56 57 58 59 5a 5b 5c 5d 5e 95
000060 60 61 62 63 64 65 66 67 68 69 6a 6b 6c 6d 6e 111
000070 70 71 72 73 74 75 76 77 78 79 7a 7b 7c 7d 7e 127
000080 80 81 82 83 84 85 86 87 88 89 8a 8b 8c 8d 8e 143
000090 90 91 92 93 94 95 96 97 98 99 9a 9b 9c 9d 9e 159
takk@deb9:~$ 

と、書くだけで、変換できてしまいます。

では、タイトルの通り、 各フィールドを左右入れ替えてみます。

フィールド数は、変数NFに格納されるので、$1~$NFまでをforで処理すればよいです。

takk@deb9:~$ seq 0 255 | perl -ne 'print chr' | od -tx1 -Ax | head | awk '{for(n=NF;n >=1;n--){r[NF-n+1]=$n}for(n=1;n<=NF;n++){$n=r[n]}print $0;}'
0f 0e 0d 0c 0b 0a 09 08 07 06 05 04 03 02 01 00 000000
1f 1e 1d 1c 1b 1a 19 18 17 16 15 14 13 12 11 10 000010
2f 2e 2d 2c 2b 2a 29 28 27 26 25 24 23 22 21 20 000020
3f 3e 3d 3c 3b 3a 39 38 37 36 35 34 33 32 31 30 000030
4f 4e 4d 4c 4b 4a 49 48 47 46 45 44 43 42 41 40 000040
5f 5e 5d 5c 5b 5a 59 58 57 56 55 54 53 52 51 50 000050
6f 6e 6d 6c 6b 6a 69 68 67 66 65 64 63 62 61 60 000060
7f 7e 7d 7c 7b 7a 79 78 77 76 75 74 73 72 71 70 000070
8f 8e 8d 8c 8b 8a 89 88 87 86 85 84 83 82 81 80 000080
9f 9e 9d 9c 9b 9a 99 98 97 96 95 94 93 92 91 90 000090
takk@deb9:~$ 

残念ながらawkはリストがないので、一発reverseができません。ちまちまforするしかありません。

forを2回使いたくない場合。

takk@deb9:~$ seq 0 255 | perl -ne 'print chr' | od -tx1 -Ax | head | awk '{for(a=1;a <=NF/2;a++){b=(NF-a+1);tmp=$a;$a=$b;$b=tmp}print $0;}'
0f 0e 0d 0c 0b 0a 09 08 07 06 05 04 03 02 01 00 000000
1f 1e 1d 1c 1b 1a 19 18 17 16 15 14 13 12 11 10 000010
2f 2e 2d 2c 2b 2a 29 28 27 26 25 24 23 22 21 20 000020
3f 3e 3d 3c 3b 3a 39 38 37 36 35 34 33 32 31 30 000030
4f 4e 4d 4c 4b 4a 49 48 47 46 45 44 43 42 41 40 000040
5f 5e 5d 5c 5b 5a 59 58 57 56 55 54 53 52 51 50 000050
6f 6e 6d 6c 6b 6a 69 68 67 66 65 64 63 62 61 60 000060
7f 7e 7d 7c 7b 7a 79 78 77 76 75 74 73 72 71 70 000070
8f 8e 8d 8c 8b 8a 89 88 87 86 85 84 83 82 81 80 000080
9f 9e 9d 9c 9b 9a 99 98 97 96 95 94 93 92 91 90 000090
takk@deb9:~$ 

こちらの方がきれいでしょうか。

Leave a Reply

Your email address will not be published. Required fields are marked *

CAPTCHA