Personal tools
You are here: Home ブログ 井上 ifconfigの出力をsedでパース
« July 2009 »
Su Mo Tu We Th Fr Sa
      1 2 3 4
5 6 7 8 9 10 11
12 13 14 15 16 17 18
19 20 21 22 23 24 25
26 27 28 29 30 31  
Recent comments
Re:Google Chromeの発表には驚きました 安定したブラウザ 2009-05-25
Re:JavaScriptライブラリのバージョンアップ問題 n 2009-05-24
Re:関数型言語Grassの勉強会資料公開(by 岩永さん) inoue 2009-05-24
Re:ソフトウェアのマニュアル管理に適したツール? Anonymous User 2009-04-26
Re:ソフトウェアのマニュアル管理に適したツール? inoue 2009-04-21
Re:ソフトウェアのマニュアル管理に適したツール? Anonymous User 2009-04-19
Re:笑いの神は降りてこなかった Anonymous User 2009-04-16
Re:情報フロー制御とBLP Anonymous User 2009-03-15
Re:JavaはCより速かった tnanba 2009-03-12
Re:JavaはCより速かった inoue 2009-03-05
Re:サーバサイドJavaScript Anonymous User 2009-03-03
Re:サーバサイドJavaScript Anonymous User 2009-03-03
Categories
カテゴリなし
 
Document Actions

ifconfigの出力をsedでパース

GNU/LinuxでローカルのIPアドレス、ブロードキャストアドレス、ネットマスクを取得するコード例は以下のようになります。

#include <stdio.h>
#include <string.h>
#include <unistd.h>
#include <sys/ioctl.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <net/if.h>
#include <arpa/inet.h> /* for inet_ntoa() */

int main(int argc, char **argv)
{
    struct ifreq ifr;
    const char *ifname = "eth0";

    int sock = socket(AF_INET, SOCK_DGRAM, 0);
    strcpy(ifr.ifr_name, ifname);
    ifr.ifr_addr.sa_family = AF_INET;
    if (ioctl(sock, SIOCGIFADDR, &ifr) == 0) {
      struct sockaddr_in *sin = (struct sockaddr_in*)&ifr.ifr_addr;
        printf("%s\n", inet_ntoa(sin->sin_addr));
    }
    if (ioctl(sock, SIOCGIFBRDADDR, &ifr) == 0) {
      struct sockaddr_in *sin = (struct sockaddr_in*)&ifr.ifr_broadaddr;
        printf("%s\n", inet_ntoa(sin->sin_addr));
    }
    if (ioctl(sock, SIOCGIFNETMASK, &ifr) == 0) {
      struct sockaddr_in *sin = (struct sockaddr_in*)&ifr.ifr_netmask;
        printf("%s\n", inet_ntoa(sin->sin_addr));
    }
    close(sock);
    return 0;
} 

コード例を見てわかるように"eth0"というネットワークインターフェース名に依存したコードになっています。 ifconfigコマンドは、/proc/net/devファイルを開いてインターフェース名を取得しています。

AirOneでローカルIPアドレスを取得する必要があります。上のようなコードを書くのが面倒なので、ifconfig(1)の出力をパースしています。次のようなシェルスクリプトです。

LANG=C /sbin/ifconfig -a | sed -n '/.*inet addr:\([0-9.]*\).*Mask:\([0-9.]*\)/{s//\1 \2/;p;q}'

これは少し問題がありました。lo(loopback)インターフェースが先に現れると、そのアドレスを拾ってしまいます。loインターフェースは読み飛ばす必要があります。grepを挟むか、あるいはsedをperlで書き換えるかと迷いましたが、次のように簡単にsedで書けました。perl使ったら負けだと思っていました。

LANG=C /sbin/ifconfig -a | sed -n '/^lo/,/^$/d; /.*inet addr:\([0-9.]*\).*Mask:\([0-9.]*\)/{s//\1 \2/;p;q}'

動作を簡単に説明します。-nオプションで暗黙の出力を抑制しています。この例のようにマッチしたパターンだけを表示したい場合には有効なオプションです。/^lo/,/^$/d でひとかたまりです。dの部分がコマンドです。カッコをつけて /^lo/,/^$/{d} と書くこともできます。// の中はそれぞれ正規表現です。loで始まる行と空行です。カンマでつなぐと、それぞれの正規表現にマッチする間コマンドを実行、という意味になります。dコマンドはパターンスペース(入力行)を削除して、次の行を読み込みます。-nオプションを指定している場合、単に入力行を無視して次の行を読む、と見なして構いません。後続する部分は // で囲まれた正規表現がマッチ条件で、{}で囲まれた部分がコマンドです。sは置換、pは出力、qは終了です。実に直感的な命名です。

PerlやEmacsのようななんでもできるツールは勝って当然、sedで勝つところが醍醐味です。例えて言えば、激ペナでボールになる変化球ばかり使って打ち取るのがPerlやEmacsで、ストレート一本、ストライク勝負で打ち取るのがsedの世界です。

The URL to Trackback this entry is:
http://dev.ariel-networks.com/Members/inoue/we-love-sed/tbping
Add comment

You can add a comment by filling out the form below. Plain text formatting.

(Required)
(Required)
(Required)
This helps us prevent automated spamming.
Captcha Image


Copyright(C) 2001 - 2006 Ariel Networks, Inc. All rights reserved.