それマグで!

知識はカップより、マグでゆっくり頂きます。 takuya_1stのブログ

習慣に早くから配慮した者は、 おそらく人生の実りも大きい。

IPアドレスをソートする (sort コマンド編:区切り文字利用)ドメインのソートも可能

IPアドレスをソートする

sort コマンドでip addr をソートすると、文字列順になってしまう。

なのでIP アドレスを文字列でソートすると、めんどくさい

解決策

  1. sort コマンドのオプションつける(この記事)
  2. ip addr を int にする。別記事
  3. sort -V を使う。

まずは、sort コマンドのオプションで解決する方法を探る

IPアドレスをソートするなら、-V オプションでバージョン番号としてソートするのが速い。

## 最速解決
sort -V

上記のような方法が不可能な環境もある、この記事私が想定しているのはbusyboxのsort や BSDのSortコマンドも含め考えたい。

ip アドレスのソートの問題。

たとえば、次を実行すると。

cat << EOS | sort
172.16.10.1
172.16.1.10
172.16.10.2
EOS

実行結果は正しい(ように錯覚する)

172.16.1.10
172.16.10.1
172.16.10.2

しかし、次を実行すれば

cat << EOS | sort
172.16.10.2
172.16.1.1
172.16.2.10
EOS

実行結果は「文字列」としてソートされてるとわかる。

172.16.1.1
172.16.10.2
172.16.2.10

sort オプションでの解決。

sort コマンドのオプションで解決させてみる。

sort -n -k 3 -t '.'

オプションについては、次のように指定してる。

# -t は区切りを指定
# -k はカラムを指定する最大2個
# -n は数字順に並べる。

実行例

cat << EOS | sort -n -k 3 -t '.'
172.16.1.1
172.16.2.10
172.16.10.2
EOS

実行結果

172.16.1.1
172.16.2.10
172.16.10.2

ただ、これだと、一つのオクテットしかソートされない。

そこで、複数のカラムに対して「数字順にソートする」

sort  -t '.' -k 3,3n -k 3,4n

第1,2オクテットも対象にしたい。

そこで、-k を重ねがけする。

ip アドレスのソート

sort -t '.'  -n -k 1,2 -k 3,4

-k は2つまでだけど、複数書ける。

なので、3,4 オクテットと1,2 オクテットを別々にオプションとして指定している。

実行例

cat <<EOS | sort -t '.'  -n -k 1,2 -k 3,4
192.168.12.11
192.168.2.11
192.168.21.11
172.16.21.11
172.16.121.11
10.1.1.11
10.10.10.11
10.2.10.11
EOS

実行結果

10.1.1.11
10.10.10.11
10.2.10.11
172.16.21.11
172.16.121.11
192.168.2.11
192.168.12.11
192.168.21.11

ただ、これだと、1,2オクテットが文字列になってしまう。開始と終了で数字評価指定するのは困難だ。

そこで、重ねがけにオプション -k, --key=KEYDEF をちゃんと指定する。

KEYDEF は F[.C][OPTS][,F[.C][OPTS]] の書式で、開始位置と停止位置を指定します。

F はフィールド番号で、 C はフィールド内の文字位置です。両方とも開始番号は 1 で す。 停止位置はデフォルトでは行末です。-t と -b の両方とも指定がない場合、 フィールド内の文字は、前にある空白の開始から数えられます。 OPTS には、1 文字の 並び替えオプション [bdfgiMhnRrV] を一つ以上指定します。 OPTS で指定されたキー の並び替えオプションは、グローバルな並び替えオプション より優先されます。キー が指定されない場合、行全体がキーとして使用されます。 正しくないキーの使用を突 き止めるには --debug を使ってください

( man sort より抜粋)

いい感じにやるには、-k の重ねがけしかない。

cat <<EOS |  sort  -t '.' -k1,1n -k 2,2n -k 3,3n -k 4,4n
192.168.12.11
192.168.2.11
192.168.21.11
172.16.21.11

ドメイン名の場合

echo dns10.quad9.net dns.opendns.com doh.opendns.com dns11.quad9.net | xargs -n 1 | sort -t '.'  -k2

などとすれば、ある程度はソートできる。 sort コマンドは最終カラム(末尾フィールド列)を指定する方法がないので、これ以上の詳細なソート(ドメイン名・パス)などはawk などほかのツールと組み合わせる必要がある。

ip v4アドレスはオクテットと表記が固定されているので、この記事のようなソートコマンドによるソートが可能です。

ip v6 アドレスは省略記法があるので、ドメイン名とおなじく、sort単体で並べるのは難しい。省略記法を使ってない、または、省略記法展開するという場合においてはv6アドレスもソートが可能。

まとめ

これで、IPアドレスを数字順にソートすることができる。

sort  -t '.' -k1,1n -k 2,2n -k 3,3n -k 4,4n

オプションをつければgnu の基本的なコマンドだけで ip アドレスを扱えることがわかる。

v6の場合は、HEXなのでちょっとめんどくさい。また今度考えることにする。

関連資料

sort を区切り文字でカラム指定出そーつとする場合。 sortコマンドで列を指定、数順など指定する。 - それマグで!

参考資料

man sort