tips – grep で前後の行も表示させるには

マッチ行直前の行を表示するには -B {行数}(または –before-context={行数})を、直後の行を表示するには -A {行数}(または –after-context={行数}) を指定します。
 
例: sh のマニュアル(manpage)から grep 検索する。
オプションなし(ただし -n は行番号を表示してわかりやすくするため付加しています)

$ man sh | grep -n UNIX
1378: A sh command, the Thompson shell, appeared in Version 1 AT&T UNIX. It
1379: was superseded in Version 7 AT&T UNIX by the Bourne shell, which inher-
1383: Bourne shell from AT&T System V.4 UNIX.

 
直前と直後 1 行ずつ表示

$ man sh | grep -n -A 1 -B 1 UNIX
1377-HISTORY
1378: A sh command, the Thompson shell, appeared in Version 1 AT&T UNIX. It
1379: was superseded in Version 7 AT&T UNIX by the Bourne shell, which inher-
1380- ited the name sh.

1382- This version of sh was rewritten in 1989 under the BSD license after the
1383: Bourne shell from AT&T System V.4 UNIX.
1384-

CVS 入出力 を支援する PEAR パッケージ

PHP5.1 以降には fgetcsv(), fputcsv() という関数が標準で提供されていますが、別の選択肢として PEAR でも File_CSV というクラスが提供されています。
 
このクラスは File パッケージに含まれています。

pear install File

 
■利用例(tests/parser.php を改変したもの)
ファイルから読み込む

<?php
require_once ‘File/CSV.php’;
 
$file = “test.csv”;
 
$conf = File_CSV::discoverFormat($file); // ファイルからデータ構造を判別(区切文字やクォーテーションなど)
while ($fields = File_CSV::read($file, $conf)) { // 取得したデータ構造を利用して行単位で読み取る
    print_r($fields);
}

ファイルから配列に読み込む

<?php
require_once ‘File/CSV.php’;
 
$file = “test.csv”;
 
$conf = File_CSV::discoverFormat($file); // ファイルからデータ構造を判別(区切文字やクォーテーションなど)
while ($fields = File_CSV::read($file, $conf)) { // 取得したデータ構造を利用して行単位で読み取る
    print_r($fields);
}

CSV ファイルの中身をすべて配列として読み込む

<?php
require_once ‘File/CSV.php’;
 
$file = “test.csv”;
 
$conf = File_CSV::discoverFormat($file); // ファイルからデータ構造を判別(区切文字やクォーテーションなど)
while ($fields = File_CSV::read($file, $conf)) { // 取得したデータ構造を利用して行単位で読み取る
    print_r($fields);
}

ファイルから配列に読み込む

<?php
require_once ‘File/CSV.php’;
 
$file = “test.csv”;
 
$conf = File_CSV::discoverFormat($file); // ファイルからデータ構造を判別(区切文字やクォーテーションなど)
$data = File_CSV::readAll($file, $conf); // 取得したデータ構造を利用し、配列として全て取得する。
var_dump($data);
<<
ファイルに書きこむ例:

<?php
require_once ‘File/CSV.php’;
 
$file = “test.csv”;
 
// 書き込む内容
$data = array(
array(“foo”, “boo”, “woo”),
array(“fo\”o”, “bo,o”, “woo”), // エスケープが必要な文字を含むレコード
);
// CSV 書式
$conf = array(
    ‘fields’ => count($data[0]), // カラム数
    ‘sep’ => “,”, // 区切り子
    ‘quote’ => ‘”‘, // 囲み文字
    // ‘header’ => false, // NULL 以外を指定すると, read 時に一行目をヘッダとみなして各要素のキーとして扱う
);
// 書きこみ実行
foreach($data as $row) {
    File_CSV::write($file, $row, $conf); //
}

 
ファイルの書きこみ制御ができなかったり、設計上気になる点もありますが、
単純に読み書きするのには十分そうです。

CUI 上の日本語表示/入力関係の ports

FreeBSD の CUI 環境から(X 一切なしで)コンソールで日本語入力ができないものか、と試行錯誤した結果次のような構成で落ち着きました。
  
OS: FreeBSD 6.2
日本語入力サーバ(Canna): japanese/canna (/etc/rc.conf で canna_enable=”YES” とする)
Canna 用辞書: japanese/cannadic (インストール方法は /usr/local/share/doc/cannadic/README.ja を参照)
日本語表示: japanese/kon2-16dot または japanese/kon2-14dot
日本語入力(UIM + Canna): japanese/uim-canna
  
CUI での日本語入力は kinput2 が主流ですが、X サーバが必要だったので今回は UIM を選択しました。
  
– その他あると便利なもの:

w3m: www/w3m-m17n
jless(less): japanese/jless
jvim (vi,vim): japanese/jvim3-canna
emcws (emacs): japanese/emacs-emcws

  
– 使い方:

$ kon
$ uim-fep
$ echo “ハローワールド”

とし、 canna[ C – R] のような文字列が下に表示されたら Ctrl-\ で日本語入力ができます。また、uim-fep は tty に依存しないのでリモートからも使えます。
 
ちなみに kon 以外の選択肢として, Linux の Framebuffer を用いた jfbtermがあり、FreeBSD 版も Yusuke Baba 氏により公開されています。)。
jfbterm と w3m-img for FreeBSD framebufferと組み合わせることで画像も表示できるようですが、jfbterm の画面切り替え時のオーバーヘッドに耐え切れず利用は断念しました。

cygwin で nice

nice / renice を使うと起動するプロセスや起動済のプロセスの優先度を変更することができます。
 
nice の書式:

nice [-n 数値 ] 実行するコマンド [引数] ..

例:

$ nice -n 10 sleep 100 # nice 10 sleep 100 は間違い

 
renice: の書式:

renice 数値 [ [-p] PID ] [ [-g] pgrps] [ [-u] ユーザ]

指定した PID (またはプロセスグループ(PGID)、ユーザ)のプロセスの優先度を指定した数値に基づいて変更します。
Cygwin で実行する場合、PID にはWindows 上の実 PID (WINPID)ではなく、Cygwin で ps すると見られる仮想 PID を指定します。
 
例1: PID で指定

$ sleep 50 &
[1] 1448
$ renice 10 -p 1448

例2: PGID で指定

$ ps
      PID PPID PGID WINPID TTY UID STIME COMMAND
     2264 2248 2264 316 con 11363 13:31:29 /usr/bin/sleep
     2168 2248 2168 2168 con 11363 13:31:33 /usr/bin/bash
     2948 2168 2168 2920 con 11363 13:31:33 /usr/bin/sleep
$ renice 19 -g 2168 # PGID が 2168 の全てのプロセスが対象

例3: ユーザ名で指定( cygwin 経由で起動しているプロセスのうち実行ユーザが john のプロセス全ての優先度を -10 (通常以上)にする)

$ renice -10 -u john

 
Windows XP で実行した場合のプロセス優先度の対応表:

nice -n

プロセス優先度

12以上

4 〜 11

通常以下

-4 〜 3

通常

-12 〜 -5

通常以上

-19 〜-13

-20 以下

リアルタイム

参考:
起動するプログラムの優先度を変更する方法(@IT)
タスクマネージャを使った変更方法と、cmd.exe の start コマンドを使った優先度指定方法についてかかれています。

文字列への文字単位のアクセスで波括弧が非推奨にかわった

ふと PHP のドキュメントを眺めていたら、次のように書かれていました
PHP: 文字列(English)

注意: $str{42} のように波括弧を使用してアクセスすることも可能です。 しかし、角括弧を使用する方法のほうが推奨されます。 なぜなら、{波括弧} 形式は PHP 6 で廃止される予定だからです。
 
Note: They may also be accessed using braces like $str{42} for the same purpose. However, using square array-brackets is preferred because the {braces} style is deprecated as of PHP 6.

PHP5 リリース前は

$str = “foo”; echo $str[0];

が非推奨で

$str = “foo”; echo $str{0};

が推奨されていましたが、方針転換をしたようです。
 
参考:
2004 年 3 月のマニュアル同項(English)(archive.org)

波括弧の後に任意の文字をゼロから始まるオフセットで指定することに より、文字列内の文字にアクセスすることが可能です。
 
    注意: 過去の互換性のため、配列括弧を使用することが可能です。しかし、 この構文はPHP 4に依存しています。
    
 Characters within strings may be accessed and modified by specifying the zero-based offset of the desired character after the string in curly braces.
  
    Note: For backwards compatibility, you can still use array-braces for the same purpose. However, this syntax is deprecated as of PHP 4.

以前はこうなっていました。

最新版の ffmpeg をダウンロードするには

ffmpeg とは、高機能な動画編集ツールです。

以前、この ffmpeg アプリのWindows版を探し回った事があったため、配布サイトをまとめてみました。
 
ffmpeg.org
公式サイト。
 
Windows用のffmpegコンパイル済バイナリは以下のサイトで配布されています。

ffmpeg 公式 Windows バイナリダウンロードページ:

https://ffmpeg.zeranoe.com/builds/

ダウンロードは、リンク先のボタンを押すだけです。

バージョンが古い可能性があるのであまりおすすめはしませんが、他にもフリーソフトに付属しているものを使うこともできます。
お気に入りの動画を携帯で見よう
SVN の HEAD を追いかけて Windows 用にビルドしたバイナリを配布しているサイト。
MingW での ffmpeg のビルド方法や依存するライブラリについても書かれています。
 
ImageMagick
ImageMagick は一部のビデオフォーマットを扱うために ffmpeg を使っているため、ffmpeg.exe をバンドルしています。
Windowsユーザでインストーラが不要な方はImageMagickのFTPサーバから、実行ファイルだけのダウンロードもできます。ファイル名が”ImageMagick-(バージョン番号)-Q16-windows.zip”のものがインストーラなし版です。
 
携帯動画変換君
ffmpegのインターフェイスとして動作するソフトです。ffmpeg が同梱されていますが、2010年9月現在、何年も更新されていないためバージョンは古めの様子。
 


Linux用 RPM は http://packages.sw.be/ffmpeg/ で最新版が順次配布されているようです。

バグパターン – switch のデータ型は複数種類にすると予期しない結果になる

まずはサンプルコードを見て、結果を予想してみてください。

<?php
$result = true;
switch($result){
  case “error”: // エラー
    echo “failure”;
    exit;
  case “ok”: // 成功
  case true: //
    echo “success”;
    exit;
  default:
    echo “unexpected”;
    exit;
}
?>

一見、このコードを実行すると success が出力されるように思いますが、実際に実行してみると意外なことに failure が出力されてしまいます。
PHP の switch 文は、switch の引数と case で指定した値とを= ではなく) でチェックしているため、switch 引数が複数の種類の型になる場合は型変換などにより予想外の値と一致することになってしまうのが原因です。
 
実際どの値が何と一致するかについては以下の検証コードを実行してみると分かります。

// 検証コード:
<?php
// values to test
$targets = array(
   0,
   1,
   true,
   false,
   null,
   “”,
   “0.00e5”,
   “10f”,
   “0f”,
   array(),
   array(1),
   array(“key”=>”foo”),
);
 
// —-
foreach($targets as $target){
  if(is_bool($target))
      $s = $target? “true”: “false”;
  elseif(is_null($target))
      $s = “null”;
  elseif(is_string($target))
      $s = “‘{$target}'”;
  else
      $s = $target;
  echo $s .”(“.gettype($target).”)”.”:\t”;
  switch($target){ //”0.00e5″
    case ‘a’: echo “case a”; break;
    case ‘b’: echo “case b”; break;
    case ‘0’: echo “case zero”; break;
    case 10: echo “case int 10”; break;
    case 0: echo “case int 0”; break;
    default: echo “default”; break;
  }
  echo “\n”;
}

php 4.4.6 および php 5.2.3 で試したところ、実行結果次のようになりました。

0(integer): case a
1(integer): default
true(boolean): case a
false(boolean): case zero
null(NULL): case int 0
”(string): case int 0
‘0.00e5′(string): case zero
’10f'(string): case int 10
‘0f'(string): case int 0
Array(array): default
Array(array): default
Array(array): default

同じ empty 値でも 0, null, false, “” で結果が全く異なってしまいました。
また、 == について挙げられる数値文字列の比較時の問題(“0.00e5” == “0” が真になる,など)の影響も受けてしまっています。
 
この問題は、型チェックを厳密にしたり、strval(), intval() などで明示的に文字列,数値キャストを行い、switch 文の引数の型が一種類になることを保証することである程度回避できます。
しかし依然として数値として有効な文字列同士の比較の問題があるため、数値を含む文字列について正確さが必要な場合や、本当に複数型を判別させたい場合は= 演算子を使い if – elseif – else を使うほうが賢明でしょう。

if($result = true || $result= “ok”){
  echo “success”;
}elseif(empty($result) || $result
= “error”){
  // empty($result) は以下の式と等価。
  // ( !isset($result) || ($result= false || $result = null ||
  // $result= “” || $result = 0 )
  echo “failure”;
}else{
  echo “unexpected”;
}

 
参考:
switch 構文(php.net)
比較演算子(php.net)
strval()(php.net)

SQL の基礎 – JOIN (表結合)の意味の違い

MySQL / PostgreSQL / Oracle すべてのSQLサーバで基準になっているSQL標準のJOIN(LEFT JOINなど)について、基礎からしっかりまとめてみました。
続きを読む SQL の基礎 – JOIN (表結合)の意味の違い