他のコマンドを起動してそのプロセスに出力、そのプロセスから入力することはそれぞれできたので、次はその両方を同時にしてみる。つまりUnix.open_processを使ってプロセスにデータを送り、結果を取得してみる。
以下は、pasteコマンドを起動して入出力し、一列のリストをリストのリストに変換するもの。
pasteコマンドにデータを送ったあとclose_outでout_channelを閉じないとin_channelからきちんと結果を取得できないようだ。
#load "unix.cma";;
#load "str.cma";;
let rec columns_aux_out oc = function
| [] -> ()
| x :: xs ->
output_string oc (x ^ "\n");
columns_aux_out oc xs;;
let rec columns_aux_in ic lst =
let line, eof =
try input_line ic, false with End_of_file -> "", true
in
if eof then
List.rev lst
else
columns_aux_in ic (line :: lst);;
let columns_aux_in ic = columns_aux_in ic [];;
let columns n lst =
if n <= 0 then
invalid_arg "columns";
let rec mkcmd n s =
if n <= 0 then s else mkcmd (n - 1) (s ^ " -")
in
let cmd = mkcmd n "/usr/bin/paste" in
let ic, oc = Unix.open_process cmd in
columns_aux_out oc lst;
close_out oc;
let result = columns_aux_in ic in
ignore (Unix.close_process (ic, oc));
List.map (fun x -> Str.split (Str.regexp "\t") x) result;;
実行例は次のようになる。リストを3要素づつのリストのリストに変換している。
# columns 3 ["1"; "2"; "3"; "4"; "5"; "6"; "7"; "8"; "9"];;
- : string list list = [["1"; "2"; "3"]; ["4"; "5"; "6"]; ["7"; "8"; "9"]]