1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54
|
open Pcre
let parse_args () =
let quick = ref false
and first = ref false
and ignore_case = ref false
and offset = ref 0
and pat = ref None
and substr = ref None in
let q = "-q", Arg.Set quick,
"Quick replacement. Interpretes substitution as plain text."
and f = "-f", Arg.Set first, "Replace first occurrence in line only."
and i = "-i", Arg.Set ignore_case, "Ignore case."
and ofs = "-ofs", Arg.Int (fun n -> offset := n),
"Start matching at column n."
and usage =
"Usage: subst [-q] [-f] [-i] [-ofs offset] pattern substitution\n\n\
Reads lines from standard input and replaces occurrences of\n\
the PERL-style regular expression \"pattern\" with \"substitution\",\n\
printing the result to standard output.\n\
In default mode the contents of \"substitution\" will be interpreted\n\
similarly to its equivalent in PERL.\n"
and anon_arg arg =
match !pat, !substr with
| None, _ -> pat := Some arg
| _, None -> substr := Some arg
| _ -> raise (Arg.Bad "too many arguments!") in
let args = [q; f; i; ofs] in
Arg.parse args anon_arg usage;
let flags = if !ignore_case then [`CASELESS] else [] in
let rex, sstr =
match !pat, !substr with
| Some rex, Some sstr -> regexp ~flags rex, sstr
| _ -> prerr_endline (Sys.argv.(0) ^ ": not enough arguments!");
Arg.usage args usage; exit 1 in
match !quick, !first with
| false, false -> fun s -> replace ~rex ~pos:!offset ~templ:sstr s
| true, false -> fun s -> qreplace ~rex ~pos:!offset ~templ:sstr s
| false, true -> fun s -> replace_first ~rex ~pos:!offset ~templ:sstr s
| true, true -> fun s -> qreplace_first ~rex ~pos:!offset ~templ:sstr s
let _ =
let substitute = parse_args () in
foreach_line (fun line ->
try print_endline (substitute line)
with Invalid_argument _ -> print_endline line)
|