カテゴリー : 2006年 8月

シェルの for ループで for file in $filelist とした時の問題と対策


複数のファイルに対する処理を for ループで行うと

for file in file1 file2 ‘file3 abc’; do
  ls $file
done

のように書け、

file1
file2
file3 abc

のような結果になりますが、
ユーザが指定したファイル群に対して処理をしたいとき、for ループで次のようにすると

$filelist=”
file1
file2
‘file3 abc’

for file in $filelist; do
  ls $file
done

とすると、

file1
file2
‘file3
abc’

となってしまいます。
 
この対策として . でスペースを置換するアドホックな対応をしてみました。

filelist=”
file1
file2
‘file3 abc’

for file in ` echo “$filelist” | sed -e ‘s/\\./\\\\./g’ -e ‘s/ /./g ‘`; do # 既存の “.” は “\.” に, ” ” は “.” に置換
    file=`echo “${file}” | sed -e ‘s/\\./ /g’ -e ‘s/\\\\././g’` # 置換を元に戻す
    ls “$file” # “” で囲むのは必須
done

結果:

file1
file2
file3 abc

 
他にいい方法があれば是非御連絡を m(. .)m

画像の伸縮


1. 単純に -resize を使った場合、アスペクト比を維持する。

convert from.png -resize 600×100 to.png

結果: from.png が 1000×1000 の場合、 100×100 に変換される
 
2. サイズ指定の最後に ! を付与すると、アスペクト比を無視する。

convert from.png -resize 600×100\! to.png

結果: 元のピクセルサイズによらず、600×100 になる。
 
などなど。
 
なお、単純に伸縮するだけでフィルタ処理( -filter, -support)をしないなら、-scale のほうが速いようです。

convert from.png -scale 600×100\! to.png

 
参考:
- ブログの木村研 – ImageMagick Tips#03 オプションでさらに便利に
- ImageMagick – Command-line Options#resize

権限があっても削除/変更不可能にする


Linux なら chattr, FreeBSD なら chflags を使うことで、 root 権限でも rm -f で削除不可にすることが可能です。
たとえば /bin ディレクトリ以下すべてを削除不可能にするには

# Linux
chattr +i /bin

 

# BSD
chflags schg /bin/* /bin

 
とすれば削除できなくなります。
 
参考:
- http://www.linux.or.jp/JF/JFdocs/Chroot-BIND-HOWTO-2.html
- UNIX の部屋 chflags
- FreeBSD memo – jail の作り方
- MANPAGE of chflags

Windows 用高機能仮想端末


Poderosa
http://ja.poderosa.org/
 
タブ式 GUI、プラグインで拡張可能な端末らしいです。
あちこちに何本もコネクション張るので、タブなのは便利そうです。
 
なお、動作には .NET Framework 2.0 を必要とします。

無償で使える VMWare Player


タダで使える仮想 PC
http://mcn.oops.jp/wiki/index.php?VM%2FVMware%2FVMware%20Player
参考:
- ttt: (VMware) FreeBSD 2.2.9-RELEASE のインストール(笑)

PEAR – DB から MDB2 への移行


PEAR :: Package :: DB

This package been superseded by MDB2 but is still maintained for bugs and security fixes
(意訳: このパッケージの代わりに MDB2 が使われるようになりましたが、バグ、セキュリティの修正はまだ続けられています)

とあったので、PEAR::DB から PEAR::MDB2 への移行について書かれているサイトをメモしておきます。
 
DB to MDB2 migration
 
参考/情報元:
- PEAR::MDB2
- MDB2 Homepage

PHP で HTTP 認証情報を取得する


HTTP 認証に成功した上でスクリプトにアクセスした場合、

$_SERVER['PHP_AUTH_USER']

に HTTP 認証した時のログインユーザ名が格納されます。
認証に失敗した、あるいは認証が行われていない場合は空になるため、
この変数を調べることでログイン状態を調べることが可能です。
 
参考:
- PHP による HTTP 認証(公式マニュアル)

Flash の IE 仕様変更対応のための汎用 JavaScript クラス


<object> が自動でアクティブ化しなくなった([2006-04-18] 参照)対策には
SWFObject (旧 FlashObject )を使うと楽に対応できます。

<script type=”text/javascript” src=”../js/swfobject.js”></script>
<!– 略 –>
<div id=”flashcontent”></div>
<script type=”text/javascript”><!–
// SWFObject(filepath, id, width, height, version, bgcolor)
var so = new SWFObject(“main.swf”, “foo”, 960, 640, “6″, “#FFFFFF”);
so.write(“flashcontent”); // id=flashcontent に対して書き出し
 
// 今回の肝はここまで。
//–></script><noscript>
<!– JavaScript OFF の時は既存の object, embed タグを表示 –>
<object classid=”clsid:d27cdb6e-ae6d-11cf-96b8-444553540000″
       codebase=”http://fpdownload.macromedia.com/pub/shockwave/cabs/flash/swflash.cab#version=6,0,0,0″
       width=”960″ height=”640″ id=”foo” align=”middle”>
<param name=”movie” value=”main.swf”><param name=”bgcolor” value=”#FFFFFF”>
<embed src=”main.swf” loop=”false” menu=”false” quality=”high” bgcolor=”#FFFFFF”
 width=”960″ height=”640″ name=”foo” align=”middle”
 type=”application/x-shockwave-flash”
 pluginspage=”http://www.macromedia.com/go/getflashplayer”>
</object>
</noscript>

 
なお、SWFObject は MIT ライセンスで公開されているため、制限なく利用が可能です。
 
参考:
- SWFObjectのドキュメントを日本語に翻訳してみたよ
- SWFObject(公式 / 上の原文)

RDBMS で任意のレコードが、指定した条件、順序の時に何番目になるかを調べる SQL 文について


SELECT * FROM a_table WHERE condition ORDER BY a, b DESC, c

の場合は、ID の a,b,c の値をそれぞれ an, bn, cn とした時、
前からの位置 n
{n| 0 <= n < (SELECT COUNT(*) FROM a_table)}は

SELECT COUNT(*) AS n FROM a_table WHERE
 condition AND
 (
   (a < an) OR
   (a = an AND b > bn) OR
   (a = an AND b = bn AND c < AS cn )
 ) — … (A)

の結果となる。
 
例:

NO: 0 1 2 3 4 5 6 7 8 9 10 11
ID: 0 1 3 5 7 9 10 11 15 20 21 23
 a: 1 1 1 1 2 2 2 2 3 3 3 3
 b: 4 4 2 0 3 2 1 1 4 3 3 3
 c: 0 1 0 2 3 3 2 3 2 3 3 4

テーブルの内容が上記の NO を除いた ID, a, b, c を属性として持ち
検体の ID が 10 の時
a < an を満たす要素は an == 2 なので 4 個 ..(1)
a = an AND b > n を満たす要素は bn == 1 なので 2 個 ..(2)
a = an AND b = bn AND c < AS cn を満たす要素は cn == 2 なので 0 個 ..(3)
全ての計算は排他なので (A) の結果は (1)+(2)+(3) = 6
これは 0 番目から数えた時の 位置 NO に一致する。

PHP_Error とエラー処理


PEAR を利用しているとよく

$res = $conn->query(“SELECT no_such_field FROM a_table”);
if(PEAR::isError($res)){ // DB::isError($res) も同じ
   die($res->getMessage()); // エラー表示して終了
}

という表記をしますが、全ての PEAR パッケージについて統一的にエラー処理したい場合は PEAR::setErrorHandling() というメソッドが有用です。
 
たとえば、次のコードは上のものと同様の結果になります。

// PEAR_ERROR_DIE: PEAR_Error がインスタンス化されたら getMessage() を出力して終了するようにする。
PEAR::setErrorHandling(PEAR_ERROR_DIE);
// あとは普通に実行
$res = $conn->query(“SELECT no_such_field FROM a_table”);
// ※ここでエラー処理は不要!

 
詳細なエラー処理を行いたい場合は PEAR_ERROR_CALLBACK を利用します。

// 例1:
PEAR::setErrorHandling(PEAR_ERROR_CALLBACK, “var_dump”);
// エラー発生時に
// if(PEAR::isError($res)){ var_dump($res); }
// とするのと等価
 
// 例2:
PEAR::setErrorHandling(PEAR_ERROR_CALLBACK, “error_exit”);
function error_exit($pear_err){
  die($pear_err->getMessage().”:”.$pear_getDebugInfo());
}
// エラー発生時にユーザ定義関数 error_exit を呼び出すのと等価

 
static に呼ばずインスタンスメソッドとして setErrroHandling をコールした場合、そのインスタンスについてのみ、ハンドリングします。
 
参考:
- PEAR 基底クラス – はじめに