まさはる's Weblog

まさはる's Weblog
Macintoshとオーディオの話題
Terminal

2004年7月29日

libwww-perl-5.800のインストール

Category : Terminal / Posted at 2004年7月29日 21:13

 Perlの使い方が少々分かってきたので、LWP::SimpleとLWP::UserAgentモジュールを使ってみたくなり、CPANに登録されているlibwww-perl-5.800をインストールしてみました。
 libwww-perl-5.800のreadmeによると、インストールには予めURI、MIME-Base64、HTML-Parser、libnet(後で分かったのですが、必要なのはNet::FTPモジュールのようです)、Digest-MD5がインストールされていなければならないようなので、Mac OS Xに標準でインストールされていないURIとHTML-Parserを先にインストールします。

● URI-1.31のインストール

$ curl -O http://www.perl.com/CPAN/modules/by-module/URI/URI-1.31.tar.gz
$ tar xzf URI-1.31.tar.gz
$ cd URI-1.31
$ perl Makefile.PL
$ make
$ make test
$ sudo make install
$ cd ..

● HTML-Tagset-3.03のインストール
 HTML-Parser-3.36のインストールにはHTML::Tagsetモジュールが必要なので、先にHTML-Tagset-3.03をインストールします。

$ curl -O http://www.perl.com/CPAN/modules/by-module/HTML/HTML-Tagset-3.03.tar.gz
$ tar xzf HTML-Tagset-3.03.tar.gz
$ cd HTML-Tagset-3.03
$ perl Makefile.PL
$ make
$ make test
$ sudo make install
$ cd ..

● HTML-Parser-3.36のインストール

$ curl -O http://www.perl.com/CPAN/modules/by-module/HTML/HTML-Parser-3.36.tar.gz
$ tar xzf HTML-Parser-3.36.tar.gz
$ cd HTML-Parser-3.36
$ perl Makefile.PL
$ make
$ make test
$ sudo make install
$ cd ..

● libwww-perl-5.800のインストール

$ curl -O http://www.perl.com/CPAN/modules/by-module/LWP/libwww-perl-5.800.tar.gz
$ tar xzf libwww-perl-5.800.tar.gz
$ cd libwww-perl-5.800
$ perl Makefile.PL
$ make

 make testの前に、apache-listing.tの下記の行を削除しないと、リンク切れのアドレスのためテスト時にエラーが出てしまいます。

$ vim t/live/apache-listing.t
"http://gump.covalent.net/jars/?C=N&O=D", この行を削除

 削除後は普通に、

$ make test
$ sudo make install
$ cd ..

 これでLWP::SimpleとLWP::UserAgentモジュールを含む多くのモジュールが/Library/Perl/5.8.1/以下にインストールされます。さて、インストールしたモジュールを使って、何を作ろうかな...(^_^;

このページのトップに戻る

2004年7月24日

Perlを使ってみました(その4)

Category : Terminal / Posted at 2004年7月24日 16:49

 その後、Getopt::Stdモジュールを利用して、いくつかの便利そうなオプションを追加しました。

ヘルプの出力
hオプションでヘルプを出力

実行結果
sオプションでユーザーエージェントに「Mac」のある行を出力してみました
#!/usr/bin/perl -w
use strict;
use Getopt::Std;
# ログファイルの整理プログラム log.pl ver. 1.3
 
# 入力するログファイルのフォーマット
# host ident authuser date "request" status bytes "referer"
# "user-agent"\n
# date = [day/month/year:hour:minute:second zone]
# day 2桁, month 3文字, year 4桁, hour 2桁, minute 2桁, second 2桁
# zone (+|-)4桁
# request = command pass HTTP/*.*
# status 3桁
 
# 初期設定
# 回数をカウントするリクエストのパスの末尾(-p|r|h|uの場合に有効)
my @count = qw( / .html .xml .rdf );
my %counter = ();
my %opt = ();
 
# オプション設定
getopts ('pruaPUs:S:c:l:h', \%opt);
if (! $opt{p} && ! $opt{r} && ! $opt{u} && ! $opt{a} &&
    ! $opt{P} && ! $opt{U}) {
    $opt{p} = 1;                        # 出力の標準
}
if (! $opt{c} || $opt{c} < 20 || $opt{c} > 256) {
    $opt{c} = 79;                       # 出力桁の標準値
}
if (! $opt{l} || $opt{l} < 1) {
    $opt{l} = -1;                       # 出力行の標準値
}
if ($opt{s}) {
    print "-s search pattern: ", $opt{s}, "\n";
}
if ($opt{S}) {
    print "-S search pattern: ", $opt{S}, "\n";
}
if ($opt{h}) {
    print "ログファイルの整理プログラム ver. 1.3\n" .
    "log.pl [-p|r|u|a|P|U]\n" .
    "       [-s search_pattern] [-S search_pattern]\n" .
    "       [-c output_columns] [-l output_lines] [-h]\n\n" .
    "出力オプション\n" .
    "p アクセス先を回数でソート(passの前半を出力)\n" .
    "  オプション指定が無い場合の出力の標準\n" .
    "r アクセス元を回数でソート(refererの前半を出力)\n" .
    "u アクセス者を回数でソート(hostの後半を出力)\n" .
    "a ブラウザ  を回数でソート(user-agentの前半を出力)\n" .
    "P クライアントエラーを出したアクセス先を回数でソート\n" .
    "U クライアントエラーを出したアクセス者を回数でソート\n" .
    "s search_pattern 正規表現のパターンにマッチする場合出力\n" .
    "S search_pattern 正規表現のパターンにマッチしない場合出力\n" .
    "c output_columns 指定桁まで出力(値は20..256,標準は79桁出力)\n" .
    "l output_lines   指定行まで出力(値は1以上,  標準は全て出力)\n" .
    "h ヘルプを出力\n";
    exit 0;
}
 
# 標準入力からのログファイルの読み込み
foreach (<STDIN>) {
    my($host, $request, $status, $referer, $agent) =
    /^(\S+).+\[\S+ \S+\] "([^"]+)" (\d{3}) .+ "([^"]+)" "([^"]+)"\n/;
 
    # 該当行の抽出
    my $out = 0;
    if ($opt{p} || $opt{r} || $opt{u} || $opt{a}) { # -p|r|u|aの場合
        foreach (@count) {
            # パスの末尾が合致し、かつstatusが200番の行を抽出
            if (($request =~ /\S+ .*$_ \S+$/) && ($status == 200)) {
                $out = 1;
                last;
            }
        }
    } elsif ($opt{P} || $opt{U}) {      # -P|Uの場合
        if ($status =~ /4\d\d/) {       # statusが400番台の行を抽出
            $out = 1;
        }
    }
 
    # ハッシュに該当行を格納
    if ($out == 1) {
        my $key ="";
        if ($opt{p} || $opt{P}) {       # -p|Pの場合
            $request =~ /^\S+ (\S+) \S+$/;
            $key = $1;
        } elsif ($opt{r}) {             # -rの場合
            $key = $referer;
        } elsif ($opt{u} || $opt{U}) {  # -u|Uの場合
            $key = $host;
        } elsif ($opt{a}) {             # -aの場合
            $key = $agent;
        }
        if ((! $opt{s} && ! $opt{S}) || # -s|Sオプションなし
        ($opt{s} && ! $opt{S} && $key =~ /$opt{s}/) || # -sの時
        ($opt{S} && ! $opt{s} && $key !~ /$opt{S}/) || # -Sの時
        ($opt{s} && $opt{S} &&          # -s-Sの時
        $key =~ /$opt{s}/ && $key !~ /$opt{S}/)) {
            if (exists $counter{$key}) {
                $counter{$key}++;       # キーがあればカウントアップ
            } else {
                $counter{$key} = 1;     # キーがなければ作成
            }
        }
    }
}
 
# 標準出力への書き出し
if (keys %counter > 0) {                # %counter が空でなければ表示処理
 
    # カウントの大きい順にソート
    my @list = sort {
        $counter{$b} <=> $counter{$a} or
        $a cmp $b                       # カウントが同じ場合はキーでソート
    } keys %counter;
    if ($opt{l} != -1 && $opt{l} < @list) {
        for (1..@list - $opt{l}) {      # 不要な行を削除
            pop @list;
        }
    }
 
    # 出力
    my $c_len = length $counter{$list[0]};  # カウントの文字数
    my $a_len = $opt{c} - $c_len - 12;  # キーの文字数
    foreach (@list) {
        my $star = "*" x int $counter{$_} / $counter{$list[0]} *
        10 + 0.5;
        my $access = $_;
        if ($opt{u} || $opt{U}) {       # -u|Uの場合は後半を出力
            $access = substr($_, -$a_len, $a_len);
        }
        printf "%10s %" . $c_len . "d %-." . $a_len . "s\n",
            $star, $counter{$_}, $access;
    }
}

 -sと-Sオプションの引数は正規表現で入力するのですが、上記プログラムは少し問題があります。例えば、「ne.jp」の正規表現は、メタキャラクタの「.」をにバックスラッシュを付けて、ne\.jpとすれば良いのですが、このプログラムの場合はオプションを%optに代入するまでの間にバックスラッシュが1つ使われてしまうようで、ne\\.jpとしないと正常に動作しません。どこで使われてしまうのかな...(?_?;

 ふと、正規表現の文字列を「"」や「'」で括ってみたところ、正常に動作するようになりました。なーんだ...(^_^;

ロボット?
Mozilla/x.0を含む行を除くと、ロボットっぽいものばかりに...
このページのトップに戻る

2004年7月10日

Perlを使ってみました(その3)

Category : Terminal / Posted at 2004年7月10日 21:10

 ようやく、ハッシュの使い方とソートの仕方を覚えたので、データの出現頻度が高い順にソートして出力するブログラムに改良しました。

#!/usr/bin/perl -w
use strict;
# ログファイルの整理プログラム log.pl [-p|r|h|P|H] ver.1.2
 
# 入力するログファイルのフォーマット
# host ident authuser date "request" status bytes "referer"
# "user-agent"\n
# date = [day/month/year:hour:minute:second zone]
# day 2桁, month 3文字, year 4桁, hour 2桁, minute 2桁, second 2桁
# zone (+|-)4桁
# request = command pass HTTP/*.*
# status 3桁
 
# 出力オプション
# p アクセス先を回数でソート(標準)
# ********** 999999 pass(前半40文字)
# r アクセス元を回数でソート
# ********** 999999 referer(前半40文字)
# h アクセス者を回数でソート
# ********** 999999 host(後半40文字)
# P クライアントエラーを出したアクセス先を回数でソート
# ********** 999999 pass(前半40文字)
# H クライアントエラーを出したアクセス者を回数でソート
# ********** 999999 host(後半40文字)
 
# 回数をカウントするリクエストのパスの末尾(-p|r|hの場合に有効)
my @count = qw( / .html .xml .rdf );
my %counter = ();
my $option = '-p';
if (@ARGV) {
    if ($ARGV[0] =~ /^-[prhPH]/) {
        $option = shift @ARGV;
    }
}
 
foreach (<STDIN>) {
    /^(\S+).+\[\S+ \S+\] "([^"]+)" (\d{3}) .+ "([^"]+)" "[^"]+"\n/;
    my $host = $1;
    my $request = $2;
    my $status = $3;
    my $referer = $4;
    my $key = '';
    my $out = 0;
    if ($option =~ /[prh]/) {        # -p|r|hの場合
        foreach (@count) {
            if (($request =~ /\S+ .*$_ \S+$/) &&
            ($status == 200)) {
                $out = 1;
                last;
            }
        }
    } elsif ($option =~ /[PH]/) {    # -P|Hの場合
        if ($status =~ /4\d\d/) {
            $out = 1;
        }
    }
    if ($out == 1) {
        if ($option =~ /[pP]/) {     # -p|Pの場合
            $request =~ /^\S+ (\S+) \S+$/;
            $key = $1;
        } elsif ($option =~ /r/) {   # -rの場合
            $key = $referer;
        } elsif ($option =~ /[hH]/) {    # -h|Hの場合
            $key = $host;
        }
        if (exists $counter{$key}) {
            $counter{$key}++;        # キーがあればカウントアップ
        } else {
            $counter{$key} = 1;      # キーがなければ作成
        }
    }
}
 
my @list = sort {                    # カウントの大きい順にソート
    $counter{$b} <=> $counter{$a} or
    $a cmp $b                        # カウントが同じ場合はキーでソート
} keys %counter;
foreach (@list) {                    # 出力
    my $star = '*' x int $counter{$_} / $counter{$list[0]} * 10 + 0.5;
    my $access = $_;
    if ($option =~ /[hH]/) {         # アクセス者の場合は後半40文字
        $access = substr($_, -40, 40);
    }
    printf "%10s %6d %-.40s\n", $star, $counter{$_}, $access;
}

 C'S SERVER Personalのログファイルは、日毎にzipで圧縮されているので、zcatの出力をパイプで入力すると便利です。

実行結果
7月のログファイルを入力してみました

 なお、このプログラムのソートでは、出現頻度が同じ場合はキーの文字列を先頭からソートしています。本来、ソートの対象がアクセス者(host)の場合は、ドット(.)区切りのワード毎に後ろからソートすべきだと思いますが、使用上問題がないので簡略化しています。(一言でいうと手抜きですね...(^_^;)

このページのトップに戻る

2004年7月 5日

Perlを使ってみました(その2)

Category : Terminal / Posted at 2004年7月 5日 23:16

 前回、「リンク元が同じものを1行にまとめるプログラム」というものを作ってみたのですが、一体どんな意味があるのかと思い考えてみたところ、あまり意味がないことに気づきました*1...(^_^;
 そこで、refererをチェックするのではなく、requestをチェックして、「1アクセスを1行にまとめるプログラム」に改良しました。

#!/usr/bin/perl -w
use strict;
# ログファイルの整理プログラム log.pl [-dhqDHQ] ver.1.1
# オプション d:date, h:host, q:request を整形して出力
#            D:date, H:host, Q:request を整形せずに出力
 
# 入力するログファイルのフォーマット
# host ident authuser date "request" status bytes "referer"
# "user-agent"\n
# date = [day/month/year:hour:minute:second zone]
# day 2桁, month 3文字, year 4桁, hour 2桁, minute 2桁, second 2桁
# zone (+|-)4桁
# request = command file-pass-name HTTP/*.*
 
# 出力するログファイルの標準フォーマット(-dhq)
# date host request
# date = day/month/year:hour:minute:second
# day 2桁, month 3文字, year 4桁, hour 2桁, minute 2桁, second 2桁 計20桁
# host 後半20文字
# request 前半37文字
 
my @delete = qw/ .jpg .gif .cgi .css .ico .sit .txt /; # 除外する拡張子名
my $option = '-dhq';
if (@ARGV) {
    if ($ARGV[0] =~ /^-[dhqDHQ]/) {
        $option = shift @ARGV;
    }
}
 
foreach (<STDIN>) {
    /(^\S+).+(\[\S+ \S+\]) "([^"]+)".+"[^"]+" "[^"]+"\n/;
    my $host = $1;
    my $date = $2;
    my $request = $3;
 
    # 除外する拡張子を持つファイルをリクエストしている行は出力しない
    my $out = 1;                                # 初期値 = 出力する
    foreach (@delete) {
        if ($request =~ /$_/) {
            $out = 0;                           # 出力しない
            last;
        }
    }
 
    # 出力
    if ($out == 1) {
        if ($option =~ /d/) {                   # 秒まで
            print substr($date, 1, 20), ' ';
        } elsif ($option =~ /D/) {              # そのまま
            print "$date ";
        }
        if ($option =~ /h/) {                   # 後半20文字
            printf "%20.20s ", substr($host, -20, 20);
        } elsif ($option =~ /H/) {              # そのまま
            print "$host ";
        }
        if ($option =~ /q/) {                   # 前半37文字
            $request =~ /^\S+ (\S+) \S+/;
            print substr($1, 0, 37);
        } elsif ($option =~ /Q/) {              # そのまま
            print "\"", $request, "\"";
        }
        print "\n";
    }
}

 ただでさえPerlっぽい部分が少ないのに、さらに少なくなってしまいました。なお、@deleteに除外する拡張子名(例えば.xmlとか.rdf等)を半角スペースで区切って追加すると、それらのファイルを要求している行が出力されなくなります。

実行結果
前回と微妙に違いますな...w
*1 削除しようかと思いましたが、Perlで作った初めてのプログラムなので、記念に曝しておきます...(^_^;
このページのトップに戻る

2004年7月 4日

Perlを使ってみました

Category : Terminal / Posted at 2004年7月 4日 17:47

 C'S SERVER Personalのサブドメインサービスはアクセスログを取得できるので、面白半分でエディタで開いてみたところ、あまりの量の多さにびっくり(これまで見たことなかったもので...(^_^;)。よく見ると、1ファイルの転送が1行で記録されており、トップページに1度アクセスしただけで20行程のログ...。こりゃ人間の見るものじゃないなと思い、リンク元が同じものを1行にまとめるプログラムを作ってみることにしました。

 プログラムの作成には、文字列の扱いが簡単にできそうで、かつインターネットで広く使われているPerl*1を使うことにしました。早速、オライリー・ジャパン初めてのPerl 第3版*2(通称「リャマ本」)を買ってきて、本を見ながら作ってみました。

#!/usr/bin/perl -w
use strict;
# ログファイルの整理プログラム log.pl [-dhrDHR] ver.1.0
# オプション d:date, h:host, r:referer を整形して出力
#            D:date, H:host, R:referer を整形せずに出力
 
# 入力するログファイルのフォーマット
# host ident authuser date "request" status bytes "referer"
# "user-agent"\n
# date = [day/month/year:hour:minute:second zone]
# day 2桁, month 3文字, year 4桁, hour 2桁, minute 2桁, second 2桁
# zone (+|-)4桁
 
# 出力するログファイルの標準フォーマット(-dhr)
# date host referer
# date = day/month/year:hour:minute:second
# day 2桁, month 3文字, year 4桁, hour 2桁, minute 2桁, second 2桁 計20桁
# host 後半20文字
# referer 前半37文字,自分のサイトアドレスは / に置き換える
 
my $my_site = 'http://masaharu.la.coocan.jp/blog/';   # 自分のサイトアドレス
my $check = 10;                                # 遡ってチェックする行数
my @before_host = (' ') x $check;
my @before_referer = (' ') x $check;
my $option = '-dhr';
if (@ARGV) {
    if ($ARGV[0] =~ /^-[dhrDHR]/) {
        $option = shift @ARGV;
    }
}
 
foreach (<STDIN>) {
    /(^\S+).+(\[\S+ \S+\]) "[^"]+".+"([^"]+)" "[^"]+"\n/;
    my $host = $1;
    my $date = $2;
    my $referer = $3;
 
    # 遡ったチェック行数内で host と referer が同じ場合は出力しない
    my $out = 1;                               # 初期値 = 出力する
    foreach (0..$check - 1) {
        if (($host eq $before_host[$_]) && 
        ($referer eq $before_referer[$_])) {
            $out = 0;
            last;
        }
    }
    pop @before_host;                          # 配列の末尾を削除
    pop @before_referer;
    unshift @before_host, $host;               # 配列の先頭に追加
    unshift @before_referer, $referer;
 
    # 出力
    if ($out == 1) {
        if ($option =~ /^-.*d/) {              # 秒まで
            print substr($date, 1, 20), ' ';
        } elsif ($option =~ /^-.*D/) {         # そのまま
            print "$date ";
        }
        if ($option =~ /^-.*h/) {              # 後半20文字
            printf "%20.20s ", substr($host, -20, 20);
        } elsif ($option =~ /^-.*H/) {         # そのまま
            print "$host ";
        }
        if ($option =~ /^-.*r/) {
            if ($referer =~ /^($my_site)/) {   # 前半36文字
                print '/', substr($referer, length($my_site), 36);
            } else {                           # 前半37文字
                print substr($referer, 0, 37);
            }
        } elsif ($option =~ /^-.*R/) {         # そのまま
            print $referer;
        }
        print "\n";
    }
}

 コメント、変数の宣言及びオプション処理を除くと、10行有るか無いかって感じですね。これを実行してみるとこんな感じに...。

実行結果
7月2日のログを入れてみました

 ソートしてグラフを描かないと使い物にならないという声が聞こえてきそうですが、うちのサイトの場合、1日分だとターミナルの1ページに収まってしまい、これで十分という噂も...(^_^;
 次回は、1週間分ぐらいのデータで、グラフが描けるようなプログラムを作ってみようと思います。*3

*1 Perlを知ったのは随分前(きっとPerlの出始めの頃...)で、当時購読していた月刊アスキーに紹介記事が載っていました。その時は便利そうだなあと思いましたが、私の周りには動かせる環境が全くありませんでした。
*2 この本は、内容が丁寧で分かり易く、冗談混じりで非常に面白く読むことができます。Perl入門者には超オススメです。
*3 こういうのを(もっとレベルの高いプログラムでの話ですが...)リャマ本には「車輪の再発明」と皮肉られています。C'S SERVER PersonalではAnalogによるアクセス解析が可能なので、自分でプログラムを書く必要はないのですが、せっかくPerlを覚えたので練習にと...(^_^;
このページのトップに戻る

2003年11月 2日

w3m-0.4.1-m17n-20030308のインストール

Category : Terminal / Posted at 2003年11月 2日 13:51

 Mac OS X 10.2のターミナルでは、日本語のページで表示が崩れたりターミナルが落ちたりと、問題があったので使用を諦めていたのですが、10.3で試しにw3m-0.4.1-stable-m17n-20030308をインストールしてみたところ、ほぼ*1問題なく使用可能になったようです。

うちのホームページ
Mオプション(モノクロ)を付けてブラウズ中

● w3m-0.4.1-stable-m17n-20030308のインストール
$ curl -O http://www2u.biglobe.ne.jp/%7Ehsaka/w3m/patch/w3m-0.4.1-stable-m17n-20030308.tar.gz
$ tar xzf w3m-0.4.1-stable-m17n-20030308.tar.gz
$ cd w3m-0.4.1-stable-m17n-20030308
$ ./configure
$ make
$ sudo make install

 ./configureのところで使用するオプションを選択するよう促されます。私の場合は、以下に示す以外の項目は全てデフォルトにしています。

Which language do you prefer?
1 .. Japanese (LANG=JA)
2 .. English (LANG=EN)
[12]? 1

What is your display kanji code?
E .. EUC-JP
S .. Shift-JIS
J .. ISO-2022-JP (JIS)
U .. UTF-8
[ESJU]? U

Let's do some configurations. Choose config option among the list.
1 - Baby model (no color, no menu, no mouse, no cookie, no SSL)
2 - Little model (color, menu, no mouse, no cookie, no SSL)
3 - Mouse model (color, menu, mouse, no cookie, no SSL)
4 - Cookie model (color, menu, mouse, cookie, no SSL)
5 - Monster model (with everything; you need openSSL library)
6 - Customize
Which? 2

*1 <hr>が使われていると表示が一部崩れるようです。そのような場合は、^l(controlとL)で画面を再描画すると正常な表示に戻ります。
このページのトップに戻る

2003年10月26日

10.3のターミナル

Category : Terminal / Posted at 2003年10月26日 14:58

 10.3では、Unix関係のコマンドやアプリケーションにバージョンアップや追加が行われ、ターミナルは1.4(v100)となって2バイト文字との親和性が向上したようです。

Vimで日本語入力中
確定前の文字色が黒バックでも判別可能に

 以前は確定前の文字色が黒で固定だったので、日本語を入力したい場合はターミナルのバックを明るい色に設定する必要があったのですが、1.4からは好きなバックの色で「ことえり」によるインライン変換ができるようになりました。

 この他にも、コマンドのバージョンアップにより個々の標準出力フォーマットが変更になっていたり、X11が正式版(1.0)になったりと、多数の変更点があるようなので、おいおいと使っていきたいと思います。(コマンドの標準出力フォーマットの変更は、シェルスクリプトの変更を必要とする場合がありますので、注意が必要です。)

このページのトップに戻る

2002年12月23日

Screen-3.9.13のインストール

Category : Terminal / Posted at 2002年12月23日 01:00

 Mac OS X 10.2にはScreen 3.9.10が標準でインストールされていますが、UNICODEに対応した最新のScreen 3.9.13をインストールしてみました。

Screenで分割した状態
上半分(0 bash)はtop、下半分(1 bash)はvimが動いています

 そのままmakeすると、エラーが出て止まってしまうので、他のサイトを参考にして(ってまたかよ...(^_^;)、makeの前にosdef.hの空ファイルをtouch osdef.hで作っておく必要があるようです。また、./configureでは、--prefix=/usr/localを付けないと、/usrにインストールされるので注意が必要です。

● Screen 3.9.13のインストール
$ curl -O ftp://ftp.uni-erlangen.de/pub/utilities/screen/screen-3.9.13.tar.gz
$ tar xzf screen-3.9.13.tar.gz
$ cd screen-3.9.13
$ ./configure --prefix=/usr/local
$ touch osdef.h
$ make
$ sudo make install

 UTF-8モードで起動させるために、オプションに-Uをつけて起動させます。

$ screen -U

 なお、上図のように1つのウインドウを複数に分割するコマンドは以下のとおりです。

ウインドウ分割 ^a-S
ウインドウ分割の解除 ^a-Q
分割された他のウインドウへのカーソル移動 ^a-TAB
新しいウインドウとシェルを生成 ^a-^c(分割はしません)

 かなり高機能なので、おいおい使っていきたいと思います。

このページのトップに戻る

Vim-6.1のインストール(その2)

Category : Terminal / Posted at 2002年12月23日 00:00

 Emacsの使用を諦めてVimばっかり使っているのですが、「Vim-6.1のインストール」のインストール方法だと文字コードの自動判別が出来ません。そこで、他のサイトを参考に、文字コードの自動判別を有効にしてビルド(+iconv)し、ステータスラインに文字コードを表示することが出来たので、その方法を以下に示します。

Vim-6.1
自動判別された文字コードと改行コード(sjis,mac)

 文字コードの自動判別を有効にするには、あらかじめlibiconvをインストールしてからvimをインストールするのですが、以下に示すautoconf -o auto/configureを実行しないと+iconvにならないようです。

● libiconv-1.8のインストール
$ curl -O ftp://ftp.gnu.org/pub/gnu/libiconv/libiconv-1.8.tar.gz
$ tar xzf libiconv-1.8.tar.gz
$ cd libiconv-1.8
$ ./configure
$ make
$ sudo make install

● vim-6.1のインストール
$ curl -O ftp://ftp.vim.org/pub/vim/unix/vim-6.1-rt1.tar.gz
$ curl -O ftp://ftp.vim.org/pub/vim/unix/vim-6.1-rt2.tar.gz
$ curl -O ftp://ftp.vim.org/pub/vim/unix/vim-6.1-src1.tar.gz
$ curl -O ftp://ftp.vim.org/pub/vim/unix/vim-6.1-src2.tar.gz
$ tar xzf vim-6.1-rt1.tar.gz
$ tar xzf vim-6.1-rt2.tar.gz
$ tar xzf vim-6.1-src1.tar.gz
$ tar xzf vim-6.1-src2.tar.gz
$ cd vim61/src/
$ autoconf -o auto/configure
$ cd ..
$ ./configure --enable-multibyte
$ make
$ sudo make install

 文字コードの自動判別の設定は、~/.vimrcのset fileencodingsで自動判別させる順序*1に文字コードを書けばよく、また、ステータスラインに文字コードを表示する設定は、set statuslineの設定文字列に関数を作って入れ込めばいいようです。これらオプションの書き方は、vimをインストールしたディレクトリのshare/vim/vim61/doc/options.txtに記載されています。(関数の書き方は...パクってきたので分かりません...(^_^;*2

● サンプルの.vimrc

" .vimrc
" ()書きはデフォルト値
" ********************
" 一般
" ********************
" vi互換にしない(compatible)
set nocompatible
" バックアップをとる(nobackup)
set backup
" 記憶する履歴数(0)
set history=50
 
" ********************
" 画面
" ********************
" ルーラーを表示(noruler)
set ruler
" 入力中のコマンドを表示(noshowcmd)
set showcmd
" ステータスラインを常に表示(1)
set laststatus=2
" 行番号を表示させない(同じ)
set nonumber
" タブや改行を表示しない(同じ)
set nolist
" ステータスラインの表示項目(無し...たぶん標準は%t\ %m%h%r%=%l,%c%V\ %P)
" [1] sample.txt [type][encoding:format][+][RO]    1,1-1    All
set statusline=[%n]\ %t\ %y%{GetStatusEx()}%m%r%=%l,%c%V\ \ \ \ %P
 
" ********************
" 文章編集
" ********************
" 行頭の空白、改行、挿入モードの開始位置での削除を許す(無し)
set backspace=indent,eol,start
" 新しい行を直前の行と同じインデントにする(noautoindent)
set autoindent
" Tab文字の文字幅(8)
set tabstop=4
" cindentやautoindent時に挿入されるタブの幅(8)
set shiftwidth=4
" キーボードでTabキーを押した時に挿入される空白の量(同じ)
set softtabstop=0
 
" ********************
" 検索
" ********************
" 検索文字列が小文字の場合は大文字小文字を区別なく検索する(noignorecase)
set ignorecase
" 検索文字列に大文字が含まれている場合は区別して検索する(nosmartcase)
set smartcase
" 検索時に最後まで行ったら最初に戻る(同じ)
set wrapscan
" 検索文字列入力時に順次対象文字列にヒットさせない(同じ)
set noincsearch
 
" ********************
" 文字コード
" ********************
" 内部の文字コード(latin1)
set encoding=utf-8
" ファイルの文字コード(無し)
set fileencoding=utf-8
" 入力ファイルの自動識別(ucs-bom,utf-8,latin1)+iconvでビルドされている必要あり
set fileencodings=ucs-bom,iso-2022-jp,euc-jp,sjis,utf-8,latin1
" ファイルの改行コード(unix)
set fileformat=unix
" 入力ファイルの改行コードの自動識別(unix,dos)
set fileformats=mac,unix,dos
 
" ********************
" オートコマンド
" ********************
if has("autocmd")
    " ファイル形式の検出、プラグインとインデントのロードを有効にする
    filetype plugin indent on
    " ファイル形式がtextの場合78文字で行を分割する
    autocmd FileType text setlocal textwidth=78
    " ファイル保存時のカーソル位置を記憶する
    autocmd BufReadPost *
        \ if line("'\"") > 0 && line("'\"") <= line("$") |
        \   exe "normal g`\"" |
        \ endif
endif
 
" ********************
" 関数の定義
" ********************
" 文字エンコーディングと改行コードの取得
function! GetStatusEx()
    let str = &fileformat
    if has("multi_byte") && &fileencoding != ""
        let str = &fileencoding . ":" . str
    endif
    let str = "[" . str . "]"
    return str
endfunction

 なお、上記.vimrcのコメント行の( )書きはデフォルトの設定を記載しています。

*1 書く順序によって、自動判別がうまくいかない場合もあるようです。utf-8はlatin1よりも前に書かないとutf-8のファイルがうまく表示されません。(試行錯誤により)
*2 eval.txtとusr_41.txtあたりに記載されています。

 Mac OS X v10.3の場合は、libiconv 1.9とvim 6.2がインストール済みとなっていますが、日本語を入力したい場合はvimにマルチバイトのオプションを付けてインストールする必要があるようです。

● vim-6.2のインストール
$ curl -O ftp://ftp.vim.org/pub/vim/unix/vim-6.2.tar.bz2
$ tar jxvf vim-6.2.tar.bz2
$ cd vim62
$ ./configure --enable-multibyte
$ make
$ sudo make install

 なお、ターミナルのウインドウ設定で「非ASCII文字をエスエープする」にチェックが入っていると日本語が正しく表示されません。

このページのトップに戻る

2002年12月21日

Bashのプロンプト

Category : Terminal / Posted at 2002年12月21日 00:00

 Bash Prompt HOWTOにBashのプロンプトについて詳しい説明があるので、それを参考にプロンプト幅が一定になるように改良してみました。

CLUMNS幅のプロンプト
プロンプト幅がターミナルのカラム幅と同じになるようにプロンプトを設定

 また、システムの負荷値*1を表示して、その状態により色を変えるようにしてみました。上の図では左から、[ヒストリ番号][ユーザ名@ホスト名(負荷値)]---[カレントディレクトリ名]を表示しており、.bashrcのPS1の設定を以下のサンプルにすると、上記のようになります。

● サンプルの.bashrc(該当部分のみ)

# ********************
# CLUMNS幅のプロンプト
# ********************
function prompt_command {
    # 文字列、数値の取得
    # HOSTNAMEの.以下を削除
    strHostname=$(echo -n $HOSTNAME | sed -e "s/\..*\.//")
    # PWDのHOME以下を~に変更
    strPwd=$(echo -n $PWD | sed -e "s:^$HOME:~:")
    # システムの1分間の平均負荷の数値を抽出
    valHostLoad=$(uptime | sed -e "s/.*load averages: \(.*\...\), \(.*\...\), \(.*\...\)/\1/" -e "s/ //g")
 
    # プロンプトをCOLUMNS幅に調整
    # [xxx][user@hostname(x.xx)]---[~]$
    # Prompt全体の長さを取得
    local valPromptSize=$(echo -n "[$HISTCMD][$USER@$strHostname($valHostLoad)][$strPwd]" | wc -c | tr -d " ")
    # COLUMNSに値が入っていない場合は80を初期値とする
    local valFillSize=$(( ${COLUMNS:-80}-$valPromptSize ))
    strFill=""
    # 短い場合は$strFillに"-"を追加
    while [ $valFillSize -gt 0 ]
    do
        strFill="-$strFill"
        valFillSize=$(( $valFillSize-1 ))
    done
    # 長い場合は$strPwdの左側を"..."に置き換えて削除
    if [ $valFillSize -lt 0 ]
    then
        local valCutSize=$(( 3-$valFillSize ))
        strPwd="...$(echo -n $strPwd | sed -e "s/\(^.\{$valCutSize\}\)\(.*\)/\2/")"
    fi
 
    # システムの1分間の平均負荷に応じてカラー設定
    # bcは乗算すると小数点が入るので除算する
    local valHostLoadInt=$(echo -e "$valHostLoad/0.01\nquit\n" | bc)
    # ANSI Escape Sequences
    # 0:normal 1:bold 4:underline 5:blink 7:reverse video 8:nondisplayed
    # 30-37,39:foreground Color 39:default
    # 30:black 31:red 32:green 33:yellow 34:blue 35:magenta 36:cyan 37:white
    # 40-47,49:background Color 49:default
    # 40:black 41:red 42:green 43:yellow 44:blue 45:magenta 46:cyan 47:white
    if [ $valHostLoadInt -ge 200 ]
    then
        strHostLoadColor=31     # red
    else
        if [ $valHostLoadInt -ge 100 ]
        then
            strHostLoadColor=35 # magenta
        else
            strHostLoadColor=0  # normal
        fi
    fi
}
PROMPT_COMMAND=prompt_command
PS1='\n[$HISTCMD][$USER@$strHostname(\[\e[${strHostLoadColor}m\]$valHostLoad\[\e[0m\])]$strFill[$strPwd]\$ '

 なお、既知の問題点として、パス名に日本語を含んでいるとズレ*2てきます。

*1 負荷値はuptimeの1分間の平均値を使っていて、これは待ちスレッドの数だそうです。私が普通に使っていると1以下なので、1を超えると色の変更をするようにしていますが、使用環境によっては2ぐらいが適当かもしれません。
*2 wcで文字数を数えているのですが、日本語(utf-8)はどうやら1文字が3バイトあるため、英数2文字分の幅を3文字とカウントしてしまうところに問題がありそうです。

 上記の場合、Mac OS X v10.3では正しく表示されません。変数やコマンドの出力が変更になっているようです。

● $HOSTNAME
 10.2の場合は"コンピュータ名.local."というふうに、最後に"."が付いていたのですが、10.3では付かなくなりました。したがって、コンピュータ名をsedで抜き出している箇所でエラーになります。

strHostname=$(echo -n $HOSTNAME | sed -e "s/\..*\.//")
      ↓
strHostname=$(echo -n $HOSTNAME | sed -e "s/\..*//")

● uptime
 10.2のuptimeは、負荷の値がコンマ+空白区切りだったのですが、10.3ではコンマが無くなり空白のみになりました。これも、1分間の平均負荷をsedで抜き出している箇所でエラーになります。

valHostLoad=$(uptime | sed -e "s/.*load averages: \(.*\...\), \(.*\...\), \(.*\...\)/\1/" -e "s/ //g")
      ↓
valHostLoad=$(uptime | sed -e "s/.*load averages: \(.*\...\) \(.*\...\) \(.*\...\)/\1/" -e "s/ //g")

● エスケープシーケンス
 これは原因がよく分からないのですが、プロンプトがズレて表示されてしまいます。とりあえずエスケープシーケンスの部分を削除して使っています。

PS1='\n[$HISTCMD][$USER@$strHostname(\[\e[${strHostLoadColor}m\]$valHostLoad\[\e[0m\])]$strFill[$strPwd]\$ '
      ↓
PS1='\n[$HISTCMD][$USER@$strHostname($valHostLoad)]$strFill[$strPwd]\$ '

(2003.12.14追記)
 上記エスケープシーケンスでズレて表示される問題は、最初の \n を取り除くことで解決しました。でもなぜ...(^_^;

このページのトップに戻る

2002年10月19日

Mule-UCS-0.84のインストール

Category : Terminal / Posted at 2002年10月19日 04:00

 見栄えのするEmacsで日本語(UTF-8)を入力したい...(^_^; ということで、Mule-UCSをインストールしてみました。

Emacs-21.1
Emacs-21.1で日本語入力(Emacs-21.1はMac OS Xに付属)

● Mule-UCS-0.84のインストール
$ curl -O ftp://ftp.m17n.org/pub/mule/Mule-UCS/Mule-UCS-0.84.tar.gz
$ tar xzf Mule-UCS-0.84.tar.gz
$ cd Mule-UCS-0.84
$ emacs -q --no-site-file -batch -l mucs-comp.el
$ ( cd lisp/jisx0213; emacs -q --no-site-file -batch -l x0213-comp.el )
$ sudo cp -RL lisp /usr/share/emacs/site-lisp/Mule-UCS

● ~/.emacsの内容
(require 'un-define)
(require 'jisx0213)
(set-language-environment "Japanese")
(set-default-coding-systems 'utf-8)
(set-keyboard-coding-system 'utf-8)
(set-terminal-coding-system 'utf-8)
(set-buffer-file-coding-system 'utf-8)
(setq file-name-coding-system 'utf-8)

● ~/.bashrcへの追記内容
function emacs() { stty raw; /usr/bin/emacs $*; stty -raw; }

 これも試行錯誤を繰り返して、なんとか日本語の入力ができるようになりました。しばらく、Emacsを常用してみたいと思います。*1

 なお、上記によるインストールの場合は、/usr/share/emacs/site-lisp/という/usr/local/じゃない場所にインストールするので、元の状態に戻したい場合は「Mule-UCS」というディレクトリごと削除して下さい。

*1 その後、使っていてあまりにも不安定なため、Emacsの使用は諦めてVimを常用することにしました。

 Mac OS X v10.3のターミナルで使用してみましたが、特に不安定なところは無いようです。また、10.2の時のようにrawモードにする必要はありません。

このページのトップに戻る

Vim-6.1のインストール

Category : Terminal / Posted at 2002年10月19日 03:00

 UTF-8のファイルの内容が見れても、見るファイルがない...(^_^; ということで、UTF-8がそのまま通るVimをインストールしてみました。

Vim-6.1
Vim-6.1で日本語入力

● vim-6.1のインストール
$ curl -O ftp://ftp.vim.org/pub/vim/unix/vim-6.1-rt1.tar.gz
$ curl -O ftp://ftp.vim.org/pub/vim/unix/vim-6.1-rt2.tar.gz
$ curl -O ftp://ftp.vim.org/pub/vim/unix/vim-6.1-src1.tar.gz
$ curl -O ftp://ftp.vim.org/pub/vim/unix/vim-6.1-src2.tar.gz
$ tar xzf vim-6.1-rt1.tar.gz
$ tar xzf vim-6.1-rt2.tar.gz
$ tar xzf vim-6.1-src1.tar.gz
$ tar xzf vim-6.1-src2.tar.gz
$ cd vim61
$ ./configure --enable-multibyte
$ make
$ sudo make install

● ~/.vimrcの内容
set encoding=utf-8
set fileencoding=utf-8

 他のサイトを参考に試行錯誤を繰り返して、なんとかUTF-8でファイルが作成できるようになりました。しかしこのVimって、初心者は操作に慣れるまでが大変...。

このページのトップに戻る

lv-4.49.4のインストール

Category : Terminal / Posted at 2002年10月19日 02:00

 やっぱり、UTF-8のファイル名が見れて作れるだけでは欲求不満が...(^_^; ということで、ファイルの内容が見れるよう、他のサイトを参考にしてlvをインストールしてみました。

● lv-4.49.4のインストール
$ curl -O http://www.ff.iij4u.or.jp/~nrt/freeware/lv4494.tar.gz
$ tar xzf lv4494.tar.gz
$ cd lv4494/build
$ ../src/configure
$ make
$ mv Makefile Makefile.bak
$ sed 's/-o bin -g bin/-o root -g wheel/' < Makefile.bak > Makefile
$ sudo mkdir /usr/local/bin
$ sudo mkdir /usr/local/lib
$ sudo mkdir -p /usr/local/man/man1
$ sudo make install

● ~/.bashrcへの追記内容
alias lv='\lv -Ia -Ou8'

 上記のインストールの手順の中で「mkdir」が3行ありますが、既にディレクトリが存在する場合は不要です。私の場合、最初だったのでディレクトリがなく、うまくインストールができずに悩みました。

このページのトップに戻る

ターミナルを使いはじめました

Category : Terminal / Posted at 2002年10月19日 01:00

 昔PowerBook 2400cにインストールしていたMk Linuxではシェルにbashを使っていたので、NetInfoマネージャで自分のプロパティのshellを/bin/bashに変更して使いはじめました。とりあえず使用するために、以下の3つのファイルをEmacsを使ってホームディレクトリに作成して、Mac OS Xの中身を覗いているところです。

● ~/.bash_profileの内容

if [ -f ~/.bashrc ]
then
    . ~/.bashrc
fi

● ~/.bashrcの内容
PS1="[\u@\h \w]\$ "
alias ll='ls -lvA'

● ~/.inputrcの内容
set convert-meta off
set meta-flag on
set output-meta on

 これでなんとか日本語(UTF-8)のファイル名が見れて作れるようになりましたが、日本語(UTF-8)のファイルを見たり作ったりすることはできません。奥が深いのとOSのバージョンアップを期待して、のんびり使っていこうかと思っています。

このページのトップに戻る