(* Handy tool for managing CSV files.
- * $Id: csvtool.ml,v 1.2 2005-11-25 14:06:58 rich Exp $
+ * $Id: csvtool.ml,v 1.3 2006-06-06 16:01:52 rich Exp $
*)
open Printf
let csv = sub r c rows cols csv in
save_out ~separator chan csv
+let cmd_replace ~separator ~csv ~chan args =
+ let ncols, replacement =
+ match args with
+ | [ ncols; replacement ] -> int_of_string ncols, replacement
+ | _ ->
+ failwith "unknown arguments to 'replace' command" in
+ (* Load the replacement CSV file in. *)
+ let replacement = Csv.load ~separator replacement in
+
+ (* Compare two rows for equality be considering only the first ncols. *)
+ let rec compare ncols row1 row2 =
+ if ncols <= 0 then true
+ else
+ match row1, row2 with
+ | [], [] -> true
+ | [], _ -> false
+ | _, [] -> false
+ | x :: xs, y :: ys ->
+ let c = Pervasives.compare x y in
+ if c <> 0 then false
+ else
+ compare (ncols-1) xs ys
+ in
+
+ (* Look for rows in the original to be replaced by rows from the
+ * replacement file. This is an ugly O(n^2) hack (XXX).
+ *)
+ let csv = List.filter (
+ fun row -> not (List.exists (compare ncols row) replacement)
+ ) csv in
+ let csv = csv @ replacement in
+ save_out ~separator chan csv
+
(* Process the arguments. *)
let usage =
- "csvtool - Copyright (C) 2005 Richard W.M. Jones, Merjis Ltd.
+ "csvtool - Copyright (C) 2005-2006 Richard W.M. Jones, Merjis Ltd.
csvtool is a tool for performing manipulations on CSV files from shell scripts.
Take a square subset of the CSV, top left at row r, column c (counting
from 0), which is rows deep and cols wide.
+ replace ncols file.csv
+ Replace rows in input.csv with rows from file.csv. The first ncols
+ columns only are used to compare rows in input.csv and file.csv to
+ see if they are candidates for replacement.
+
Input and output files:
csvtool normally processes its input from stdin and writes its output
to stdout. Use the -i and -o options to override this behaviour.
cmd_square ~separator:output_sep ~csv:input ~chan ()
| "sub" ->
cmd_sub ~separator:output_sep ~csv:input ~chan args
+ | "replace" ->
+ cmd_replace ~separator:output_sep ~csv:input ~chan args
| _ -> prerr_endline (Sys.executable_name ^ " --help for usage")
);