Personal tools
You are here: Home ブログ 井上 ifconfigの出力をsedでパース
« August 2008 »
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:Software Design 2008年2月号「Emacsマスターへの道」の原稿を公開 elim 2008-07-25
Re:Rails(ActiveRecord)のJOINのイディオム inoue 2008-06-20
Re:「ピアレビュー」を読みました Anonymous User 2008-05-12
Re:「ピアレビュー」を読みました inoue 2008-05-10
Re:「ピアレビュー」を読みました Anonymous User 2008-05-09
Re:「ピープルウェア」再読 inoue 2008-04-20
Re:僅か30分で3つのバグ - Rubyの落し穴 - inoue 2008-04-20
Re:僅か30分で3つのバグ - Rubyの落し穴 - rubikitch 2008-04-19
Re:ソフトウェアインスペクションの試行 horii 2008-03-31
Re:「ピープルウェア」再読 anaka 2008-03-31
Re:WEB+DB Press Vol.43の記事への指摘 yanagisawa 2008-03-25
Re:マルスケと月刊I/O あなか 2008-03-23
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.