ITコンサルの日常

ITコンサル会社に勤務する普通のITエンジニアの日常です。

携帯が壊れた&もう直ったらしい。

愛用の812SHが壊れた。原因は子供に持たせてたら、がっつりしゃぶるわ、投げつけられるわ、色々あったかららしい。
お店に持っていったら、3Gカード(?)がショックでずれたりすると、不調になるとのこと。
3Gカードを一回はずして、やわらかい布で拭いた後、元に戻すと直ったりするらしい。
らしいって書いたのは、僕のはそれで直らなかったからだったりします。
で、工場行き〜。
子供がしゃぶったってことになると、ヘタすると水没扱いになって、多額な修理代を請求される恐れもありとのこと。ちなみに水没の原因の半分は子供のおしゃぶりなんだそうな。
なんのからくりか分からんのだが、水没扱いの修理代は14,700円。が、しかし、SKIカード(クレジット; 入会金、年会費無料)を作って、ソフトバンクの利用料をここから落とすと、水没時の修理代から12,000円引きになるという。
う〜ん。なんかはめられているような。。
クレジットカード勧誘のバイトでその道に詳しいうちの奥さんが「銀行口座の登録をやらないでおけば、勝手にキャンセルになるよ。」と悪魔のささやき。これに従って、とりあえず申し込みはしたものの、口座の書類は保留してある。
土曜日に修理に出して、今日もう直ったとの連絡がきた。この直りの早さは水没じゃなかったってことなのか?それともあきらめて丸ごと替えたから早かったのか?不明。
3週間かかるって言ったのに。
実は、奥さんが昔使ってて不満たらたらだった、803Tに3Gカード移し変えて使っていたんですが、あっという間に用済みかも。E*Tradeのサイト見られなくて不便だったんだよね。これが。いやいや、見ない方が平和だったとの見方もあるけど。
そんなわけで、多分明日には812SHが戻ってくる予定。

テキストファイルを読み込む

プログラミングC# p544

ファイル読み込みみたいな、プログラミング言語としての基本機能が、大分後になって書かれています。が、ちょっと都合で先取り。

using System;
using System.IO;

class ReadFileTest
{
        static void Main(string[] args)
        {
                FileInfo file = new FileInfo("header.txt");

                using(StreamReader sr = file.OpenText())
                {
                        string text;
                        while((text = sr.ReadLine()) != null)
                        {
                                Console.WriteLine(text);
                        }
                }
        }
}

Javaでtry〜catch〜finallyを書くよりは、using文を使うことですっきりしてます。
そういやusingキーワードは、二つの意味を持つなぁ。これ、C#のポリシに反しないのかな?
ところで、結果はこう。

HTTP/1.1 200 OK
Date: Tue, 12 Feb 2008 14:58:27 GMT
Server: Apache
Content-Type: text/html; charset=euc-jp
Vary: Accept-Encoding
Connection: close

これ、d.hatena.ne.jpにHEADコマンドを投げた結果だったりします。詳細は次のエントリ。
このテキストファイルを使って、正規表現の辺りを読み進めようと画策中。。

WebサーバにHEADコマンドを投げてみる

Windowsなら、コマンドプロンプトを開いて、

telnet www.hoge.ne.jp 80

と打ってみる。
すると、

接続中: www.hoge.ne.jp...

のように出て、接続されると画面がクリアされる。
ここですかさず

HEAD / HTTP/1.0

のように打つと、

HTTP/1.1 200 OK
Date: Tue, 12 Feb 2008 15:20:12 GMT
Server: Apache
Content-Type: text/html; charset=euc-jp
Vary: Accept-Encoding
Connection: close



ホストとの接続が切断されました。

のような結果が得られる。というわけです。

文字列の分割

プログラミングC# p248

String#Splitを使って、HTTPヘッダをフィールド名と値に分けます。

using System;
using System.IO;

class ReadHeader
{
        static void Main(string[] args)
        {
                FileInfo file = new FileInfo("header.txt");

                using(StreamReader sr = file.OpenText())
                {
                        // 最初の一行はステータス行のため読み飛ばし
                        sr.ReadLine();

                        string text;
                        while((text = sr.ReadLine()) != null)
                        {
                                char[] splitChars = {':'};
                                string[] headerValue = text.Split(splitChars);
                                Console.WriteLine("HeaderName = {0} / Value = {1}", headerValue[0], headerValue[1]);
                        }
                }
        }
}

結果はこう。

HeaderName = Date / Value =  Tue, 12 Feb 2008 14
HeaderName = Server / Value =  Apache
HeaderName = Content-Type / Value =  text/html; charset=euc-jp
HeaderName = Vary / Value =  Accept-Encoding
HeaderName = Connection / Value =  close

意図せず、時間(14:58:27)がSplitされてしまっている。
これをうまくいくよう、わざわざ正規表現を使ってやってみる。

using System;
using System.IO;
using System.Text;
using System.Text.RegularExpressions;

class ReadHeader
{
        static void Main(string[] args)
        {
                FileInfo file = new FileInfo("header.txt");

                using(StreamReader sr = file.OpenText())
                {
                        // 最初の一行はステータス行のため読み飛ばし
                        sr.ReadLine();

                        Regex theReg = new Regex("^([^:]+): (.*)$");

                        string text;
                        while((text = sr.ReadLine()) != null)
                        {
                                MatchCollection theMatches = theReg.Matches(text
);
                                foreach(Match theMatch in theMatches)
                                {
                                        Console.WriteLine("HeaderName = {0} / Va
lue = {1}", theMatch.Groups[1].Value, theMatch.Groups[2].Value);
                                }
                        }
                }
        }
}

行頭からコロンじゃない文字が1つ以上続き、コロンとスペースが現れた後、任意の文字が行末まで続くという正規表現を定義してみた。
結果はこう。

HeaderName = Date / Value = Tue, 12 Feb 2008 14:58:27 GMT
HeaderName = Server / Value = Apache
HeaderName = Content-Type / Value = text/html; charset=euc-jp
HeaderName = Vary / Value = Accept-Encoding
HeaderName = Connection / Value = close

時間も正しく表示できた。


正規表現Java

import java.io.*;
import java.util.regex.*;

class ReadHeaderRegex
{
        public static void main(String[] args) throws Exception
        {
                BufferedReader br = null;

                try
                {
                        br = new BufferedReader(new FileReader("header.txt"));

                        // 最初の一行はステータス行のため読み飛ばし
                        br.readLine();

                        Pattern p = Pattern.compile("^([^:]+): (.*)$");

                        String text = null;
                        while((text = br.readLine()) != null)
                        {
                                Matcher m = p.matcher(text);
                                if(m.matches())
                                {
                                        System.out.printf("HeaderName = %s / Val
ue = %s\n", m.group(1), m.group(2));
                                }
                        }
                }
                finally
                {
                        if(br != null)
                        {
                                br.close();
                        }
                }
        }
}

正規表現の書き方自体はもちろん同じ。結果ももちろん同じ。


正規表現Ruby

theReg = Regexp.new("^([^:]+): (.*)$");

open("header.txt") { |file|
        # 最初の一行はステータス行のため読み飛ばし
        file.gets

        while text = file.gets do
                matchData = theReg.match(text)
                puts "HeaderName = #{matchData[1]} / Value = #{matchData[2]}"
        end
}

すっきり!(^o^)
くどいようだが、正規表現の書き方自体はもちろん同じ。結果ももちろん同じ。


正規表現VBScript

Set fs = CreateObject("Scripting.FileSystemObject")
Set ts = fs.OpenTextFile("header.txt")

Set theReg = New Regexp
theReg.Pattern = "^([^:]+): (.*)$"

' 最初の一行はステータス行のため読み飛ばし
ts.ReadLine()

While ts.AtEndOfStream = False
        lineData = ts.ReadLine()

        Set matches = theReg.Execute(lineData)

        WScript.Echo "HeaderName = " & matches(0).submatches(0) & " / Value = "
& matches(0).submatches(1)
Wend

ts.Close()


正規表現JScript

var fs = new ActiveXObject("Scripting.FileSystemObject");
var ts = fs.OpenTextFile("header.txt");

var theReg = /^([^:]+): (.*)$/;

// 最初の一行はステータス行のため読み飛ばし
ts.ReadLine();

while(!ts.AtEndOfStream)
{
        lineData = ts.ReadLine();

        var matches = theReg.exec(lineData);

        WScript.Echo("HeaderName = " + RegExp.$1 + " / Value = " + RegExp.$2);
}

ts.Close();


正規表現perl

open(FILE, "header.txt");

# Skip Status Line

while(<FILE>)
{
        chomp;

        if($_ =~ /^([^:]+): (.*)$/)
        {
                print "Header = $1 / Data = $2\n";
        }
}

close(FILE);

perl版が一番手になじんだ気がした。


それにしても、カッコでくくって後から使う機能は「後方参照」とか呼ぶみたいですけど、awkとかじゃ使えないんですね。意外。