技術部ネットワーク課の上曽山です。
ログの分析や集計を行う時やコマンドの実行結果を整理する時、よくsortコマンドを使います。
最近、立て続けにsortの使い方で悩まされる場面があったので、どんなオプションを使えば適切に並び替えられるのかまとめました。
ケース1: 異なる単位の数値を並べる
ディスク使用量やファイルサイズを調べる時、human-readableな表記に変換されていると、うまくsort出来ません。
$ sudo du -sh /boot/*/ |sort 0 /boot/efi/ 1.4M /boot/extlinux/ 4.0K /boot/grub/ 8.1M /boot/grub2/
こんな時は-h
オプションを使います。
shortオプション | longオプション | 機能 |
---|---|---|
-h | --human-numeric-sort | 人間が読みやすい単位の数値を比較する |
実行結果は以下の通りです。
$ sudo du -sh /boot/*/ |sort -h 0 /boot/efi/ 4.0K /boot/grub/ 1.4M /boot/extlinux/ 8.1M /boot/grub2/
比較対象の数値が先頭に無い時は-k
と併用しましょう。
$ df -h |sort -k 2h Filesystem Size Used Avail Use% Mounted on tmpfs 1.1G 0 1.1G 0% /run/user/1000 devtmpfs 5.4G 0 5.4G 0% /dev tmpfs 5.4G 0 5.4G 0% /dev/shm tmpfs 5.4G 0 5.4G 0% /sys/fs/cgroup tmpfs 5.4G 561M 4.9G 11% /run /dev/sda1 10G 4.7G 5.4G 47% / /dev/sda4 93G 6.7G 87G 8% /mnt
-k
と併用する時はフィールドを指定する数字とオプションの間にスペースを入れないよう注意してください。
$ df -h |sort -k 2 h sort: cannot read: h: No such file or directory
ケース2: 複数のログから抽出した結果を時系列順に並べる
syslogで出力されるログは月名が英字(JanとかFebとか)になっているためsortが難しい。
例えば、ユーザー「hogehoge」が最後にFTPログインした日を調べて欲しい、と言われた時。
※以下のログはダミーです。
$ zgrep -h "hogehoge.*LOGIN" /var/log/ftp/ftp.log* Oct 10 13:30:12 example vsftpd[7785]: [hogehoge] OK LOGIN: Client "192.168.0.1" Aug 25 05:30:12 example vsftpd[3074]: [hogehoge] OK LOGIN: Client "192.168.0.1" Sep 15 18:10:11 example vsftpd[6269]: [hogehoge] OK LOGIN: Client "192.168.0.3" Jul 30 17:20:07 example vsftpd[2810]: [hogehoge] OK LOGIN: Client "192.168.0.1" Jul 27 01:10:09 example vsftpd[1389]: [hogehoge] OK LOGIN: Client "192.168.0.1" Aug 29 11:50:11 example vsftpd[2964]: [hogehoge] OK LOGIN: Client "192.168.0.2" Sep 2 16:30:12 example vsftpd[8845]: [hogehoge] OK LOGIN: Client "192.168.0.2" Sep 23 04:00:13 example vsftpd[3274]: [hogehoge] OK LOGIN: Client "192.168.0.1" Jul 16 01:20:07 example vsftpd[2058]: [hogehoge] OK LOGIN: Client "192.168.0.3"
これをsortするには-M
と-n
を使います。
shortオプション | longオプション | 機能 |
---|---|---|
-M | --month-sort | 英字の月名(Jan..Dec)で比較する |
-n | --numeric-sort | 文字列を数値として比較する |
実行結果は以下の通りです。
$ zgrep -h "hogehoge.*LOGIN" /var/log/ftp/ftp.log* | sort -k 1M -k 2n Jul 16 01:20:07 example vsftpd[2058]: [hogehoge] OK LOGIN: Client "192.168.0.3" Jul 27 01:10:09 example vsftpd[1389]: [hogehoge] OK LOGIN: Client "192.168.0.1" Jul 30 17:20:07 example vsftpd[2810]: [hogehoge] OK LOGIN: Client "192.168.0.1" Aug 25 05:30:12 example vsftpd[3074]: [hogehoge] OK LOGIN: Client "192.168.0.1" Aug 29 11:50:11 example vsftpd[2964]: [hogehoge] OK LOGIN: Client "192.168.0.2" Sep 2 16:30:12 example vsftpd[8845]: [hogehoge] OK LOGIN: Client "192.168.0.2" Sep 15 18:10:11 example vsftpd[6269]: [hogehoge] OK LOGIN: Client "192.168.0.3" Sep 23 04:00:13 example vsftpd[3274]: [hogehoge] OK LOGIN: Client "192.168.0.1" Oct 10 13:30:12 example vsftpd[7785]: [hogehoge] OK LOGIN: Client "192.168.0.1"
月名の部分を-M
で、日付の部分から後を`-n‘でsortした事になります。
ケース3: rpmパッケージをバージョン順に並べる
rpmパッケージのバージョンは数字英字が混じっているため、これまたsortしにくいものになっています。
サンプルとしてkernelのバージョンをオプション無しでsortします。
$ rpm -q kernel |sort kernel-3.10.0-1062.4.1.el7.x86_64 kernel-3.10.0-957.10.1.el7.x86_64 kernel-3.10.0-957.12.2.el7.x86_64 kernel-3.10.0-957.1.3.el7.x86_64 kernel-3.10.0-957.21.2.el7.x86_64
今度は-V
を使います。
shortオプション | longオプション | 機能 |
---|---|---|
-V | --version-sort | 自然な(バージョン)番号順で比較する |
実行結果は以下の通りです。
$ rpm -q kernel |sort -V kernel-3.10.0-957.1.3.el7.x86_64 kernel-3.10.0-957.10.1.el7.x86_64 kernel-3.10.0-957.12.2.el7.x86_64 kernel-3.10.0-957.21.2.el7.x86_64 kernel-3.10.0-1062.4.1.el7.x86_64
最後に
色んなデータ処理をする時、整理する方法が分からないと時間をかけて力技で解決したり、複数のコマンドを組み合わせてトリッキーな手段を使う事が多いかと思います。
# 私だけですかね?(汗)
よく使われるコマンドには意外と便利なオプションが用意されているので、すべてを把握するのは無理だろうけど、1回くらい試しに実行してみると視野が開けるかもしれません。