読者です 読者をやめる 読者になる 読者になる

ITの隊長のブログ

ITの隊長のブログです。いや、まだ隊長と呼べるほどには至っていないけど、日々がんばります。CakePHPとPlayFrameworkを使って仕事しています。最近はAngular2をさわりはじめたお(^ω^ = ^ω^)

mecabをphpのproc_open()を使って実行したらうまく解析されなかった件。

Mecab PHP

スポンサードリンク

哀れなできごとでした。


私はこの事象に2時間を浪費しました。


結果から先に。


mecabは改行で文章を終わりと判断します。


逆に改行がない文章の解析は不具合がでてもおかしくないってね。


なので、解析する文章は改行を付与してあげましょう。


私はこれがわからなかった。(知っていたはずだったんだけど、、、)

# 改行あり
$ echo 'テスト' | mecab
テスト	名詞,サ変接続,*,*,*,*,テスト,テスト,テスト
EOS

# 改行無し
echo -n 'テスト' | mecab
テスト	名詞,サ変接続,*,*,*,*,テスト,テスト,テスト
EOS
input-buffer overflow. The line is split. use -b #SIZE option.
テスト	名詞,サ変接続,*,*,*,*,テスト,テスト,テスト
EOS


この通り。何故か2つの文章を解析したような動作になり、また、不思議なエラーも発生するというオンパレードになります。


phpでも同じこと。


恐らく、php_mecab では、考慮されていると思いますが、自作プログラム組んでいた俺にはそんなことはわかりませんでした。

<?php

$path = '/usr/local/bin/mecab';

/* 標準入力を利用し、キーボードからの入力を受け付ける */
// 標準入力は改行をキーとして取り込められるので発生しない。
// $stdin      = fopen( 'php://stdin' , 'r' );
// $str  = fgets( $stdin );
// fclose( $stdin );

// 文字列を読み込ませる場合は必ず改行を付与してあげましょう -> 「PHP_EOL」がオススメ
$str = 'テスト'.PHP_EOL;

if (!function_exists('stream_get_contents')) {
    function stream_get_contents($handle) {
        $contents = '';
        while (!feof($handle)) {
            $contents .= fread($handle, 8192);
        }
        return $contents;
    }
}

$descriptorspec = array(
    0 => array("pipe", "r"),
    1 => array("pipe", "w"),
    2 => array("pipe", "w")
);
$result = "";
$error  = "";
$process = proc_open($path, $descriptorspec, $pipes);
if (is_resource($process)) {
    fwrite($pipes[0], $str);
    fclose($pipes[0]);

    $result = stream_get_contents($pipes[1]);
    fclose($pipes[1]);

    fwrite($pipes[2], $error);
    fclose($pipes[2]);
    proc_close($process);
}

echo $result;

これで解決しました!(どんッ!!)



あ、なるほど、変なエラー(input-buffer overflow. The line is split. use -b #SIZE option.)も、これで発生してたのかね。


aipacommander.hatenablog.jp