CIDR表記で示されたIPアドレスの範囲に含まれるかどうかを簡単に確認したい場合、シェルコマンドだけでやろうとすると難しかったので、Rubyのワンライナーを使った。

$ target_ip=`dig +short example.co.jp`
$ ruby -r 'ipaddr' -e 'p IPAddr.new("xxx.xxx.xxx.0/24").include?("ARGV[0]")' $target_ip
true

IPAddr.newはCIDR表記を受け取ることができる。CIDR表記なのでプレフィックス表記(/24)でもサブネットマスク表記(/255.255.255.0)でも問題ない。(引用元:class IPAddr

0 から IPAddr::IN6MASK までの数値を受け取ります。 また、'address', 'address/prefixlen', 'address/mask' の形式も受け付けます。 プリフィックス長やマスクが指定されると、 マスクされた IPAddr オブジェクトを返します。

IPアドレス範囲をto_rangeでRangeに変換して、その中に引数で渡したIPアドレスが含まれているかどうかを確認することもできる(IPAddr.new("xxx.xxx.xxx.0/24").to_range.include?("ARGV[0]"))のだが、IPAddrクラスにはinclude?メソッドがあり、そのままIPアドレスが自身の範囲に入っているか確認してくれる。to_rangeは範囲内のIPアドレスを一覧として表示するときなどには使えるが、今回の場合は直接include?を使用した方がいい。

確認したいIPアドレス範囲が複数個ある場合でも、ヒアドキュメントを組み合わせてワンライナーで書いてみる。ヒアドキュメントをパイプで渡して、標準入力を各行からなる配列として読む。各行に対してIPAddrクラスを使って引数で渡したIPアドレスが含まれているかどうかを確認している。

cat <<'EOS' | ruby -r 'ipaddr' -e 'p STDIN.readlines.any?{|c| IPAddr.new(c).include?(ARGV[0])}' $target_ip
xxx.xxx.xxx.0/24
yyy.yyy.yyy.0/26
EOS

先ほどからRubyワンライナー部分ではpでtrue/falseを表示しているだけだが、シェルスクリプトに上記を組み込む場合は、exitを代わりに使用して、シェルで終了ステータスを確認するとRubyとシェルの連携が簡単になる。trueであれば0が終了ステータスになり、falseであれば1が終了ステータスになる。

#!/bin/bash

target_ip=`dig +short example.co.jp`

cat <<'EOS' | ruby -r 'ipaddr' -e 'exit STDIN.readlines.any?{|c| IPAddr.new(c).include?(ARGV[0])}' $target_ip
xxx.xxx.xxx.0/24
yyy.yyy.yyy.0/26
EOS
# IPアドレスがCIDR表記で示された範囲に含まれていたら
test $? -eq 0 && echo "$target_ip is included."