シェルにおける eth0 や en0 の IP アドレスの取得のしかたと、GNU sed と BSD sed の挙動違い

Linux の場合。以下は Boot2docker の /etc/init.d/docker より。ip(8) と sed(1) を使っている。

$ ip addr show eth0
2: eth0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc pfifo_fast state UP group default qlen 1000
    link/ether d8:50:e6:4c:be:de brd ff:ff:ff:ff:ff:ff
    inet 10.0.0.64/24 brd 10.0.0.255 scope global eth0
       valid_lft forever preferred_lft forever
    inet6 fe80::da50:e6ff:fe4c:bede/64 scope link
       valid_lft forever preferred_lft forever
$ ip addr show eth0 | sed -nEe 's/^[ \t]*inet[ \t]*([0-9.]+)\/.*$/\1/p'
10.0.0.64

OS X には ip(8) が無いので ifconfig(8) を使う。そもそもで eth0 も無いが。そして驚いたことに、BSD sed は GNU sed と違い、タブを展開しない。

エスケープではなく、直接にタブ文字を入れろ、ということのようだ。 ∥ regex - How can I insert a tab character with sed on OS X? - Stack Overflow

以下は、Bash にタブを展開してもらった例。しかし、今度は \1 をエスケープする必要が生じた。

$ ifconfig en0 | sed -nEe $'s/^[ \t]+inet[ \t]+([0-9.]+).*$/\\1/p'
192.168.34.65

タブ文字を使いたくなければ、やはり sed(1) の方で、ブラケット展開の文字クラスを使って書かざるを得まい。ところがさらに、re_format(7) (BSD) に書かれていることと違って、[[:space:]]\s が等価でない問題が。

$ ifconfig en0 | sed -nEe 's/^[[:space:]]+inet[[:space:]]+([0-9.]+).*$/\1/p'
192.168.34.65
$ ifconfig en0 | sed -nEe 's/^\s+inet\s+([0-9.]+).*$/\1/p'
$ 

細かいところ、BSD は緩いのかね? Linux, OS X 両対応するなら以下で。 ∥ shell - Check if a program exists from a bash script - Stack Overflow

command -v ip &> /dev/null && \
 ip addr show eth0 | sed -nEe 's/^\s+inet\W+([0-9.]+).*$/\1/p' || \
 ifconfig en0 | sed -nEe 's/^[[:space:]]+inet[[:space:]]+([0-9.]+).*$/\1/p'

あるいは、こんなか。

(command -v ip &> /dev/null && ip addr show eth0 || ifconfig en0) | \
 sed -nEe 's/^[[:space:]]+inet[^[:alnum:]]+([0-9.]+).*$/\1/p'

追記(Feb 24 2015): eth0 や en0 の MAC アドレスが欲しい場合には、以下のような感じか。

(command -v ip &> /dev/null && ip addr show eth0 || ifconfig en0) | \
 sed -nEe 's/^[[:space:]]+(link\/)?ether[[:space:]]+([0-9a-f:]+).*$/\2/p'

追記(Apr 26 2016): Ubuntu のバージョンを上げて systemd になったせいか、NIC の命名ルールが PredictableNetworkInterfaceNames に変更になった。うちの子たちは 1 Ethernet しか積んでいないので、とりあえず一つ目に見つかった Ethernet デバイスの IP アドレスを取ってくるようにするよ。なお、DELL のハードウェアは Linux 的には特別扱いで、“biosdevname” なる、これまた別のルールで命名されるらしい。 ∥ RHEL7のNICのネーミングルール - めもめも

(command -v ip &> /dev/null && ip addr show \
 $(basename $(ls -d /sys/class/net/{en*,eth*,em*} 2> /dev/null | \
 head -n 1)) || ifconfig en0) | \
 sed -nEe 's/^[[:space:]]+inet[^[:alnum:]]+([0-9.]+).*$/\1/p'