16 · 命令行接口:参数、错误信息和退出状态
目标:让 StudyLog 接收输入路径,并使用可检查的退出状态区分成功、数据失败和用法错误。
把路径写死在源码里,每次换文件都要重新编辑程序。Sys.argv 保存命令行参数:索引 0 是程序名,后面是用户传入的内容。它是数组,我们先用 Array.to_list 转为列表,就能用已学过的模式匹配检查参数形状。
命令行程序有三个不同通道:标准输出交付结果,标准错误解释失败,退出状态让脚本判断是否成功。本课程约定 0 为成功,1 为读取或解析失败,2 为参数用法错误;1 和 2 的具体划分是本程序约定,不是所有软件必须遵守的统一规则。
实验:命令行只负责连接边界
在 studylog/ 将 bin/main.ml 完整替换为:
let usage = "Usage: studylog FILE"
let run path =
match Studylog.Store.load path with
| Error message ->
prerr_endline message;
1
| Ok sessions ->
print_endline (Studylog.Core.summary sessions);
0
let () =
let status =
match Array.to_list Sys.argv with
| [_; "--help"] ->
print_endline usage;
0
| [_; path] -> run path
| _ ->
prerr_endline usage;
2
in
exit status
run 返回整数状态,最外层才调用 exit。[_; path] 要求恰好一个用户参数,_ 忽略程序名。帮助分支必须放在普通路径分支之前,否则 --help 会被当作文件名打开。
先预测三次调用的状态,再执行:
dune exec bin/main.exe -- sample.log
echo $?
dune exec bin/main.exe -- --help
echo $?
dune exec bin/main.exe
echo $?
预期可观察到:
sessions=2 minutes=60
0
Usage: studylog FILE
0
Usage: studylog FILE
2
-- 把 Dune 的参数与应用参数分开;echo $? 必须紧接被检查的命令,中间其他命令会覆盖状态。最后一次用法提示在标准错误,终端通常会把两条输出流一起展示。
现在用已有 sample.log 的副本创建 bad.log,内容是单行 OCaml|bad,执行:
dune exec bin/main.exe -- bad.log
echo $?
预期是 line 1: minutes must be an integer,随后状态为 1。程序不会打印成功报表。不要给失败文件静默输出 0 分钟,那会让调用方误以为处理成功。
一次参数顺序实验
- 将帮助分支移到普通路径分支下面,运行帮助命令。Dune 默认开发配置可能把“冗余分支”警告视为构建错误;若所用配置允许编译,该帮助参数会按路径处理。
- 恢复分支顺序,确认帮助正常。
- 给程序传两个路径,它应显示用法并返回 2,而不是只处理第一个。
独立练习:为帮助增加短参数 -h,且保持 --help。使用 or-pattern,在同一分支中接受两种模式。检查两个帮助入口为 0、无参数为 2、坏文件为 1。
参考修改
把帮助分支替换为以下片段:
| [_; ("--help" | "-h")] ->
print_endline usage;
0
执行:
dune exec bin/main.exe -- -h
echo $?
预期显示用法并打印 0。也要重新执行上面的成功、无参数和坏文件命令,确保其他行为保持。练习结束恢复主示例;第 17 课会完整替换入口。
若路径含空格,在 shell 中加引号,例如 "my study.log"。如果真的要读取名为 --help 的文件,可以传 ./--help。本课程使用极小的手动参数解析器;复杂选项、补全与自动帮助适合以后学习专用库。
本课只替换 bin/main.ml,新增用于观察失败的 bad.log;核心、存储模块和测试保持不变。