LoginSignup
5
4

More than 5 years have passed since last update.

PHP で JUMAN を扱う(改良)

Last updated at Posted at 2015-08-23

以前、このような投稿をしました。
http://qiita.com/SOJO/items/a13ea90e63340802fa52

しかし、この方法では以下のような入力をして場合、同じ単語でも別の意味があるときは @ が付いて別の行で出力され、この結果をそのまま受け取ることになります。

$ juman
国立図書館
国立 こくりつ 国立 名詞 6 普通名詞 1 * 0 * 0 "代表表記:国立/こくりつ カテゴリ:抽象物 ドメイン:教育・学習;政治"
@ 国立 くにたち 国立 名詞 6 地名 4 * 0 * 0 "代表表記:国立/くにたち 地名:日本:東京都:市"
図書 としょ 図書 名詞 6 普通名詞 1 * 0 * 0 "代表表記:図書/としょ カテゴリ:抽象物 ドメイン:文化・芸術"
館 かん 館 名詞 6 普通名詞 1 * 0 * 0 "代表表記:館/かん 漢字読み:音 カテゴリ:場所-施設"

もしも、同じ単語として処理をする場合に後々面倒です。なので、同じ単語のものは同じ文字列にするように処理を加えました。
(2015/9/4 @mpyw さんに前の記事で指摘を受けたので,こちらも改良しました)

proc_open を使う方法

  function juman($text) {
    $descriptorspec = array(
       0 => array("pipe", "r"),  // stdin は、子プロセスが読み込むパイプです。
       1 => array("pipe", "w"),  // stdout は、子プロセスが書き込むパイプです。
    );

    $process = proc_open('/usr/local/bin/juman', $descriptorspec, $pipes);

    if (is_resource($process)) {
      // $pipes はこの時点で次のような形を取っています。
      // 0 => 子プロセスの stdin に繋がれた書き込み可能なハンドル
      // 1 => 子プロセスの stdout に繋がれた読み込み可能なハンドル
      // すべてのエラー出力は /tmp/error-output.txt に書き込みされます。

      fwrite($pipes[0], $text);
      fclose($pipes[0]);

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

      // デッドロックを避けるため、proc_close を呼ぶ前に
      // すべてのパイプを閉じることが重要です。
      proc_close($process);


      // 単語に別の意味が含まれる場合、
      // 同じ単語でも @(atmark) が付いて行が別れてしまうので、
      // それを合わせる処理
      // 配列を逆順にしてから処理することで、複数行に及ぶものにも対応
      $output = array_reverse(preg_split("/EOS|\n/", $output));
      foreach ($output as $out_key => $out_value) {
        if (isset($out_value[0]) && $out_value[0] == "@") {
          $output[$out_key+1] .= " " . $output[$out_key];
          $output[$out_key] = "";
        }
      }
      $return_value = array_filter(array_reverse($output), 'strlen'); // 空の要素を取り除く

      return $return_value;
    }
  }

shell_exec を使う方法(こちらの方が簡単)

function juman($text) {
  // jumanのコマンドを実行
  // EOSを除去し,改行で区切
  $output = shell_exec(sprintf('echo %s | /usr/local/bin/juman', escapeshellarg($text)));
  $output = array_reverse(preg_split("/EOS|\n/u", $output));

  // 単語に別の意味が含まれる場合、
  // 同じ単語でも @(atmark) が付いて行が別れてしまうので、
  // それを合わせる処理
  // 配列を逆順にしてから処理することで、複数行に及ぶものにも対応
  foreach ($output as $out_key => $out_value) {
    if (isset($out_value[0]) && $out_value[0] == "@") {
      $output[$out_key+1] .= " " . $output[$out_key];
      $output[$out_key] = "";
    }
  }
  $return_value = array_filter(array_reverse($output), 'strlen'); // 空の要素を取り除く

  return $return_value;
}
5
4
2

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
5
4