blog

Java、PHP、C++、MySQL、Apache、Linux、UnixなどのTechを紹介

PHP

PHPには、Linux、Mac、Windowsなどの異なるOS環境間で改行コードを内部的に自動で切り替えてくれるPHP_EOLという便利な定数が用意されている。Javaでの実装だとSystem.getProperty("line.separator")にあたると思う。PHP_EOLがPHPの内部ではどのように実装されているのか、いまさらながらPHP_EOLと改行コードについて書いてみた。

PHP_EOLが定義されているソースファイルをリーディングする

リーディングするソースコードのPHPバージョンはphp-5.3.1を使う。PHP_EOLの定義箇所は以下のヘッダファイルにあり、PHP_EOL以外の定義済み定数の大半もこのファイルで定義されている。

php-5.3.1/main/php.h の Line47 ~ 71あたり
#ifdef PHP_WIN32         

  #include "tsrm_win32.h"
    ・
    ・
  #define PHP_EOL "\r\n"
   // (OSがWindowsの場合に改行コードが\r\nになる)

#else
    ・ 
    ・ 
 #if defined(__MacOSX__) 
   // ※__MacOSX__このマクロはMacOS10では使われてない
   //   らしい。なのでここの条件分岐にMacOS10は入らない

   #define PHP_EOL "\r" 
    // (OSがMacOS9以前の場合に改行コードが\rになる) 

 #else

   #define PHP_EOL "\n" 
    // (OSがMacOS10、Linux、Unixなどの場合に\nになる) 

 #endif

#endif

このように、OS環境によって、if文で条件分岐し改行コードの文字表現を\r\n\r\nとdefineしているシンプルなソースコードである。わかりやすいように一覧表にまとめてみると以下の関係になり、ネットでも検索すれば同じような一覧内容は確認できる。

改行コード

各OS環境でPHP_EOLが出力する改行コードをASCIIコードで確認してみる

改行コードを標準出力しても分かりずらいので、PHPのord()関数をつかいASCIIコードに変換して出力してみたいと思う。(※Mac環境がないので、Linux、Windows環境のみで)

以下にASCIIコード一覧の抜粋があるが、そこにある太字のASCIIコードが返ってくることが予想できる。ここで問題なのがWindows環境であるCRLF(\r\n)である。そもそもCRLFというASCII文字は存在していない。いったいどのような値がかえるのか?

ASCIIコード

コマンドラインでスクリプトを実行した結果

下記、改行コードを生成するコマンドをOS環境を変えてコマンドラインから実行していってみる。またOS環境における差異を明確化させるために、strlen()関数で出力される改行コードの長さも測った。下記が結果内容である。
php -r 'echo ord(PHP_EOL);'  (改行コードをASCIIコードで出力)

Linux環境で実行した際の結果値:10
Windows環境で実行した際の結果値:13

php -r 'echo strlen(PHP_EOL);'  (改行コードの長さを出力)
Linux環境で実行した際の結果値:1
Windows環境で実行した際の結果値:2

これらの結果から、疑問であったWindows環境における改行コードのASCIIコードの値は13と出力された。ASCIIコード一覧と照らしてみると、13 = CR = \rになる。このような値が返ってきたのはCRLF自身が、ASCIIコードのCR(\r)とLF(\n)を並べて表現しているからである。現にstrlen()関数で長さを取得するとWindows環境(CRLF)では2という値がかえり、2byteの文字列であることがわかる。そのためord()関数にPHP_EOL定数がPHP内部でOS環境を判定して、\r\nをセットしても、先頭1byteの\r = 13が返ってくるというわけである。これはord()関数の異常というわけでなく、正常動作であった。

 
投稿日:2010/01/04 | カテゴリ:PHP | コメント・TrackBack:(0)
MySQL

MySQLのUDF(ユーザ定義関数)機能を使い、アルファベットの文字列をひらがな順にソートするオリジナル関数を作成してみた。このUDF関数はアルファベットの文字列データが含まれるMySQLのデータカラムに対して、日本語固有のひらがな順にソートを可能にする。漢字、ひらがなで登録された2byte文字列データであれば、MySQL自身が内部で持っている辞書データによりひらがなソートが可能なのだが、アルファベットの文字列データをソートしようとした場合は英語固有のアルファベット順ソートになってしまう。そこで今回作成した関数(alpha_to_hiragana関数と命名)内部において、アルファベットの文字列に対して、ひらがな順にソートできるように、ひらがな順にデータの重みづけの内部変換を行い、ひらがなソートを実現した。alpha_to_hiragana関数の開発ポイントを今回記述してみたいと思う。

そもそものUDF関数の実装方法を知りたい方は、下記の関連リンク先サイトがわかりやすいのでそちらを見てほしい

アルファベット順ソートとひらがな順ソートの違い

まずは、通常のソート(アルファベット順)とalpha_to_hiragana関数(ひらがな順)を 使ったソートの処理結果の違いを見てもらいたい

無秩序にならんだサンプルデータ(テーブル名:actor)

+-------------------+
| name              |
+-------------------+
| Saitou akira      |(さ行)(頭文字:S)
| L7ucky Isono      |(ら行)(頭文字:L)
| aida masao        |(あ行)(頭文字:A)
| YamadaShougo      |(や行)(頭文字:Y)
| AKAGI haruka      |(あ行)(頭文字:A)
| Mike Davis        |(ま行)(頭文字:M)
| Tanaka123         |(た行)(頭文字:T)
| hamadamayui       |(は行)(頭文字:H)
| goto satoru       |(か行)(頭文字:G)
| WANIDA KENJI      |(わ行)(頭文字:W)
| N-A-G-U-R-A-R-Y-O |(な行)(頭文字:N)
+-------------------+

アルファベットソート後(A->B->C->D->E...順に並びかえられた)

使用したクエリ:SELECT name FROM actor ORDER BY name ASC
+-------------------+
| name              |
+-------------------+
| aida masao        |(頭文字:A)
| AKAGI haruka      |(頭文字:A)
| goto satoru       |(頭文字:G)
| hamadamayui       |(頭文字:H)
| L7ucky Isono      |(頭文字:L)
| Mike Davis        |(頭文字:M)
| N-A-G-U-R-A-R-Y-O |(頭文字:N)
| Saitou akira      |(頭文字:S)
| Tanaka123         |(頭文字:T)
| WANIDA KENJI      |(頭文字:W)
| YamadaShougo      |(頭文字:Y)
+-------------------+

ひらがなソート後(あ->か->さ->た->な...順に並びかえられた)

使用したクエリ:SELECT name FROM actor ORDER BY alpha_to_hiragana(name) ASC
+-------------------+
| name              |
+-------------------+
| aida masao        |(あ行)
| AKAGI haruka      |(あ行)
| goto satoru       |(か行)
| Saitou akira      |(さ行)
| Tanaka123         |(た行)
| N-A-G-U-R-A-R-Y-O |(な行)
| hamadamayui       |(は行)
| Mike Davis        |(ま行)
| YamadaShougo      |(や行)
| L7ucky Isono      |(ら行)
| WANIDA KENJI      |(わ行)
+-------------------+

アルファベット文字列をひらがな順への重みづけ方法

YamadaTarou(やまだたろう)、TanakaMasao(たなかまさお)をサンプルデータとして説明する

  1. 文字列を小文字に変換する

  2. YamadaTarou => yamadatarou
    TanakaMasao => tanakamasao
    
  3. ローマ字読みから重みづけるための変換テーブルを作成する

  4. 以下が変換テーブルである、母音のあ行は1文字全てにアルファベットを割り当て、 子音はまとめて1文字のアルファベットを割りあてる

    あ行:あ(a)、い(b)、 う(c)、 え(d)、 お(e)
    か行:(f)
    さ行:(g)
    た行:(h)
    な行:(i)
    は行:(j)
    ま行:(k)
    や行:(l)
    ら行:(m)
    わ行:(n)
    
  5. 変換テーブルを用いて、サンプルデータを変換する

  6. y a m a d a t a r o u
    ↓
    l a k a h a h a m e c
    
    t a n a k a m a s a o
    ↓
    h a i a f a k a g a e
    
  7. 変換後のアルファベット文字列で比較を行う

  8. y a m a d a t a r o u
    
    [昇順]  h a i a f a k a g a e  <<<  l a k a h a h a m e c  [降順]
              (TanakaMasao)               (YamadaTarou)
         (たなかまさお)       (やまだたろう)
    

    このようにアルファベット文字列であっても、ひらがな順にソートを実現できるようになる。実際のソートに関しては、alpha_to_hiragana関数内で実装するのではなく、MySQLのORDER BY句で利用してひらがなソートを実現している。

興味をもたれた方は

SOURCEFORGE.JPのMySQLibプロジェクト内にUPしているので 下記よりアクセスしていただけると幸いである

  • alpha_to_hiragana関数の詳細な使用方法はこちら
  • alpha_to_hiragana関数のソースコードのダウンロードはこちら
 
投稿日:2009/06/14 | カテゴリ:MySQL | コメント・TrackBack:(0)
FreeBSD

私は主に開発作業をFreeBSD上で行っている。時にはサーバにログインして作業を行うケースもあり、SSHクライアント(OpenSSH_4.5)でサーバでアクセスする。ちょっと1~2時間休憩のために、席をはずしどってくると接続が切れてることはないだろうか? 原因の多くはルーター、サーバーで接続コネクションを切断しているからだと思もわれる。 Windows専用、SSHクライアントソフトputtyにはkeepalive機能がついていて、指定した時間に定期的に、 nullパケットをログインしているサーバに送信することにより、切断を防げるのだが、 OpenSSHクライアントには標準で同様な機能はついてないようだ。 色々と調べてみたところ、OpenSSH用のpatchを作成されている方がいたので、利用させてもらうことにした。そのときの導入方法である

今回の導入するパッチの作成者は、東北大学の後藤 英昭博士である、感謝!

導入方法

  1. OpenSSHを最新版(ver4.2 => 4.5)にする

  2. cd /usr/ports/security/openssh-portable
    

    (注意)上記OpenSSHのバージョンはこの記事を書いていた際の最新バージョンである

  3. patchのダウンロード

  4. wget http://www.sc.isc.tohoku.ac.jp/~hgot/sources/
                           openssh-4.4p1-watchdog.patch.tgz
    
  5. ダウンロードしたパッチをあて、パケット送信機能を実装する

  6. make patch
    
  7. インストール

  8. make install
    

    インストールが成功すると、/usr/local/bin/ssh にSSHクライアントが置かれる

  9. パケット送信する間隔を設定ファイルに書き込む

  10. /etc/ssh/ssh_config に Heartbeat 120
    

    上記設定は2分間隔でパケットを送るという設定になる

  11. インストールしたpatch済みのSSHクライアンと置き換えを行う

  12. CShellを使っているので、aliasを設定し置き換える
    /etc/csh.cshrcに alias ssh /usr/local/bin/ssh を追加する
    

    標準のSSHクライアントは/usr/bin/ssh にあるので、上書き置き換えでも可能だと思う

 
投稿日:2009/06/12 | カテゴリ:FreeBSD | コメント・TrackBack:(2)