第112回 JavaのI/Oは Decoratorデザインパターン だったのか

http://www.amazon.co.jp/Java-I-O-OReilly-Associates/dp/1565924851/ref=sr_1_2?ie=UTF8&s=english-books&qid=1244200256&sr=1-2


引用:

私はDecoratorを知っていて読んだので問題ありませんでしたが、Decoratorを知らない読者は依然「どうしてこんなにオブジェクトをラップする必要があるのか」分からないのではないかと思います。


少し、Decoratorパターンについて調べてみた。
502 Bad Gateway
ギコ猫とDecoratorパターン


ん〜 どういう利点があるのかわからん。このパターン。



引用:

細かいクラスを乱造したのはアナタだ、と。

こうとしか捉えられない......

第111回 はてなブックマークの Web Hook試してみましたが

#!/usr/bin/perl
use utf8;
use strict;
use warnings;
use Data::Dumper;

use CGI;

my $req = CGI->new;

open my $f, '>>log.txt';
print $f Dumper $req;
close $f;

print "Content-Type: text/plain\n\n";


ん〜〜
こない〜


日本語だと来ない気がする.......


と思って検索すると、
(開発者さま向け) はてなブックマーク Web Hook 機能を公開しました - はてなブックマーク日記 - 機能変更、お知らせなど
同じ症状の方がいらっしゃいました。



確かに、コメント(ブコメ)に日本語がはいっているとPOSTされていない気がする。
(始めはタグを含んでるとダメかと思ってが.... アルファベットで書いたタグはいけたし)



作るまで上記リンクのコメント欄読み飛ばしてしまっていた。



追記:改修されたようです。

第110回 クォートとパス名展開

*(アスタリスク)を囲うか? 囲わないか?

bashでコマンドを打つときに *(アスタリスク)を使う場面に出くわすことは多いと思います。

find / -name '*.txt'

とするとき、
「あれ? クォートいったけ? いらなかったけ?」
「この*(アスタリスク)はbashが展開する? findが展開する??
(たしか、クォートしなかった場合は、bashが展開したような....)」
となってしまいました。


この * をクォートで囲むべきなのか
はたまたダブルクォートで囲むべきなのか
いやいやクォートせずに使うべきなのか



曖昧な理解をやめるために調べてみました。

シングルクォートとダブルクォートの違いは?

http://www.linux.or.jp/JM/html/GNU_bash/man1/bash.1.html
こちらを参考に、以下引用を交えて調べていった結果を書きたいと思います。
(一部省略して引用しています)


引用:

クォートの方法には、 
エスケープ文字(escape character), シングルクォート、ダブルクォート
の 3 種類があります。 
ダブルクォートで文字を囲むと
クォート内部の全ての文字は文字としての値を保持しますが、
$, `, \ は例外となります。

なるほど
ダブルクォートは $, `, \が例外になるわけか。
ということは、*のみを使う場面ではシングルクォートを使っておくのがよいかもしれない。

パス名展開

引用:

展開はコマンドラインが単語へ分割された後に (コマンドライン上で) 行われます。
行われる展開は 7 種類あります:
  ブレースの展開 (brace expansion),
  チルダの展開 (tilde expansion),
  パラメータと変数の展開 (parameter and variable expansion),
  コマンド置換 (command substitution),
  算術式展開 (arithmetic expansion),
  単語の分割 (word splitting), 
  パス名の展開 (pathname expansion)。 

なるほどぉ
一口に展開といっても、7種類も展開があったのか、今回気になっているのは、
「パス名の展開」にあたるやつだ。



引用:

-f オプションが指定されていなければ、
単語分割を行った後に bash はそれぞれの単語が *, ?, [ を含んでいるかどうか調べます。
これらの文字のいずれかが見つかると、その単語は パターン と見なされ、
パターンにマッチするファイル名をアルファベット順にソートしたリストに置換されます。

なるほど
やはり、クォートしないとbashが展開しているのですね。


いま、以下のようなファイルがあるディレクトリで、echoを使ってみましょう。

$ ls
f10	f11	f7	f8	f9


クォートなし

$ echo *
f10 f11 f7 f8 f9

なるほど。展開されています。


クォートあり

$ echo '*'
*

なるほど。展開されていません。


findに渡すとき

ではfindで試してみましょう。


クォートなし

$ find . -name f*
find: f11: unknown option

これではfindに渡るまえにbashで展開されてしまい、f11なんていうオプションはないと怒られてしまいました。


クォートあり

$ find . -name 'f*'
./f10
./f11
./f7
./f8
./f9

うまくいきました。
findコマンドに'f*'という文字列として渡してあげて、その'f*'を、findコマンドによって解釈してもらわねばならないわけですね。

第109回 これは便利! ちょっとした技

bash

bashはデフォルトではEmacsと同じ操作ができますね。

No.1 Ctr + a

[行頭移動]


NO.2 Ctr + k

[行末までバッファにコピー]


No.3 Ctr + y

[バッファの内容を貼り付け]


No.4 Ctr + a後 Ctr + k 作業後 Ctr +y

[途中まで打った内容を保存して別のコマンド実行]


何かコマンドを途中まで打っていて、
引数の順番を忘れた..... manをみたい......
でも....... 今、manを見るとまで打った内容がおじゃんだ....

そんな状況はないだろうか?
そんなときは

行頭に移動し、
行末までを切り取り(バッファーにコピーし)、
manを見た後で貼り付ければよい。


No.5  Esc後d もしくはCtr+[後d もしくは Alt+d

[1単語削除]


エスケープを使ってもよいし、Ctr+[を使ってもよいし、Altを使ってもよいみたい。



ちなみに..........
bashではないが、ブラウザでAlt+dを押すと、アドレスバーにフォーカスする。

第108回 Oracleのお勉強 sqlplusのお勉強

sqlplusの表示は読みにくい。
それはなぜか? そこに迫ってみた。

linesize

SQL> show linesize
linesize 10

こんな感じで、linsesize の値が小さいと
すごく改行される。

SQL> select * from user_role_privs;

USERNAME
----------
GRANTED_RO
----------
ADMIN_
------
DEFAUL
------
OS_GRA
------
SYS
AQ_ADMINIS
TRATOR_ROL

以下略

表示しているターミナルの横幅のバッファサイズ

こんな風に、横幅のバッファが小さいと、
その幅で改行される。


linesizeは80あるにも限らず、早めに改行されている

SQL> show linesize
linesize 80
SQL> select * from u
ser_role_privs;

USERNAME
--------------------
--------------------
--------------------

GRANTED_ROLE

             ADMIN_
DEFAUL
--------------------

以下略

わからないこと

col カラム名 format 書式
と、毎回カラム名をしていしないと長さかえられないのだが、
これをVARCHAR2なら20バイトでとか一括で指定できないものか.....

第106回 Oracleのお勉強 GROUP BYを使って取得するものは一度に取得できないか考える

次の表で考えてみよう。

SQL> select * from (
  2    select sysdate   日付,  1 管理番号 from dual union
  3    select sysdate   日付,  2 管理番号 from dual union
  4    select sysdate   日付,  3 管理番号 from dual union
  5    select sysdate+1 日付,  1 管理番号 from dual union
  6    select sysdate+1 日付,  2 管理番号 from dual union
  7    select sysdate+1 日付,  3 管理番号 from dual
  8  );

日付       管理番号
-------- ----------
09-05-30          1
09-05-30          2
09-05-30          3
09-05-31          1
09-05-31          2
09-05-31          3

6行が選択されました。

日付ごとに最小管理番号、最大管理番号を求める


まず、効率の悪い例

最小を求める
SQL> select
  2    to_char(t1.日付, 'YYYY/MM/DD')    日付,
  3    min(t1.管理番号)                  最小管理番号
  4  from (
  5    select sysdate   日付,  1 管理番号 from dual union
  6    select sysdate   日付,  2 管理番号 from dual union
  7    select sysdate   日付,  3 管理番号 from dual union
  8    select sysdate+1 日付,  1 管理番号 from dual union
  9    select sysdate+1 日付,  2 管理番号 from dual union
 10    select sysdate+1 日付,  3 管理番号 from dual
 11  ) t1
 12  group by
 13    to_char(t1.日付, 'YYYY/MM/DD')
 14  order by
 15    to_char(t1.日付, 'YYYY/MM/DD')
 16  ;

日付                 最小管理番号
-------------------- ------------
2009/05/30                      1
2009/05/31                      1
最大を求める
SQL> select
  2    to_char(t2.日付, 'YYYY/MM/DD')    日付,
  3    max(t2.管理番号)                  最大管理番号
  4  from (
  5    select sysdate   日付,  1 管理番号 from dual union
  6    select sysdate   日付,  2 管理番号 from dual union
  7    select sysdate   日付,  3 管理番号 from dual union
  8    select sysdate+1 日付,  1 管理番号 from dual union
  9    select sysdate+1 日付,  2 管理番号 from dual union
 10    select sysdate+1 日付,  3 管理番号 from dual
 11  ) t2
 12  group by
 13    to_char(t2.日付, 'YYYY/MM/DD')
 14  order by
 15    to_char(t2.日付, 'YYYY/MM/DD')
 16  ;

日付                 最大管理番号
-------------------- ------------
2009/05/30                      3
2009/05/31                      3

最小と最大を日付ごとに結合

SQL> select
  2    t1_min.日付           日付,
  3    t1_min.最小管理番号   最小管理番号,
  4    t2_max.最大管理番号   最大管理番号
  5  from
  6    (
  7      select
  8        to_char(t1.日付, 'YYYY/MM/DD')    日付,
  9        min(t1.管理番号)                  最小管理番号
 10      from (
 11        select sysdate   日付,  1 管理番号 from dual union
 12        select sysdate   日付,  2 管理番号 from dual union
 13        select sysdate   日付,  3 管理番号 from dual union
 14        select sysdate+1 日付,  1 管理番号 from dual union
 15        select sysdate+1 日付,  2 管理番号 from dual union
 16        select sysdate+1 日付,  3 管理番号 from dual
 17      ) t1
 18      group by
 19      to_char(t1.日付, 'YYYY/MM/DD')
 20    ) t1_min,
 21    (
 22      select
 23        to_char(t2.日付, 'YYYY/MM/DD')    日付,
 24        max(t2.管理番号)                  最大管理番号
 25      from (
 26        select sysdate   日付,  1 管理番号 from dual union
 27        select sysdate   日付,  2 管理番号 from dual union
 28        select sysdate   日付,  3 管理番号 from dual union
 29        select sysdate+1 日付,  1 管理番号 from dual union
 30        select sysdate+1 日付,  2 管理番号 from dual union
 31        select sysdate+1 日付,  3 管理番号 from dual
 32      ) t2
 33      group by
 34      to_char(t2.日付, 'YYYY/MM/DD')
 35    ) t2_max
 36    where
 37      t1_min.日付     =     t2_max.日付
 38    order by
 39      t1_min.日付
 40  ;

日付                 最小管理番号 最大管理番号
-------------------- ------------ ------------
2009/05/30                      1            3
2009/05/31                      1            3

しかし、これはやはりかなり非効率だ。




効率的なやり方  (1度のGROUP BYで最小と最大はとれる)

SQL> select
  2    to_char(t1.日付, 'YYYY/MM/DD')    日付,
  3    min(t1.管理番号)                  最小管理番号,
  4    max(t1.管理番号)                  最大管理番号
  5  from (
  6    select sysdate   日付,  1 管理番号 from dual union
  7    select sysdate   日付,  2 管理番号 from dual union
  8    select sysdate   日付,  3 管理番号 from dual union
  9    select sysdate+1 日付,  1 管理番号 from dual union
 10    select sysdate+1 日付,  2 管理番号 from dual union
 11    select sysdate+1 日付,  3 管理番号 from dual
 12  ) t1
 13  group by
 14    to_char(t1.日付, 'YYYY/MM/DD')
 15  order by
 16    to_char(t1.日付, 'YYYY/MM/DD')
 17  ;

日付                 最小管理番号 最大管理番号
-------------------- ------------ ------------
2009/05/30                      1            3
2009/05/31                      1            3

これが効率のよいやり方(というか普通はこうする)。

第105回 Oracleのお勉強 CASE式とDECODEに慣れる

GROUP BYするときに、countだけでは、うまく集計できないことが多々ある。
それはもう結構ある。


そういうときは、sumとCASEもしくは、sumとDECODEである。


CASEとDECODEの違いは、
CASE と DECODE 関数の違い - オラクル・Oracleをマスターするための基本と仕組み
を参考にしていただくとして、ここでは書式に慣れたいと思う。
リンク先で

引用:

DECODE( expr, 
        comparison_expr1, ret_expr1,
        comparison_expr2, ret_expr2,
        default_expr );


CASE expr
    WHEN comparison_expr1 THEN ret_expr1 
    WHEN comparison_expr2 THEN ret_expr2
    ELSE                   default_expr
END

と とてもわかりやすく書き換えられていましたので、大変助かりました。

DECODE( 比較対象の値が, 
        この値なら,       ココの値にする,
        この値なら,       ココの値にする,
        デフォルト );


CASE 比較対象の値が
    WHEN この値なら THEN ココの値にする
    WHEN この値なら THEN ココの値にする
    ELSE デフォルト
END

こんな感じに読めるわけですね。

sum と DECODEを使う

前回の

SQL> select
  2    to_char(d_create, 'YYYY/MM/DD HH:MI:SS')     日付,
  3    c_status                                     ステータス
  4  from
  5    t_group_date
  6  ;

日付                                   ステータス
-------------------------------------- --------------------
2009/01/01 10:10:10                    5
2009/01/01 10:10:11                    5
2009/01/02 10:10:10                    5
2009/01/02 10:10:11                    0

を使って、
「日付ごとに、ステータスが5のものの件数を数える」


SQL> select
  2    to_char(d_create, 'YYYY/MM/DD')        日付,
  3    sum( decode (  c_status,
  4                          5, 1,
  5                          0
  6                 )
  7        )                                   件数
  8  from
  9    t_group_date
 10  group by
 11    to_char(d_create, 'YYYY/MM/DD')
 12  order by
 13    to_char(d_create, 'YYYY/MM/DD')
 14  ;

日付                       件数
-------------------- ----------
2009/01/01                    2
2009/01/02                    1