Lab 3:用 Rust 重新实现 cut¶
作业内容¶
本题提供 GNU cut 的使用说明和 coreutils-9.11/src/cut.c 源码。你需要借助 Agent 阅读这些材料,并用 Rust 重新实现本题要求的功能。
不要逐句翻译
请按 Rust 常见的写法重新实现,可以自由使用 Vec、迭代器、Result 和标准库的字符串方法,不需要保持 C 版本的代码结构。
不要为了照搬 C 代码而使用裸指针或 unsafe。
程序行为以 GNU coreutils 9.11 为准。
功能要求¶
cut 的作用¶
cut 是 GNU coreutils 中用于提取文本指定部分的工具。例如,文件 scores.txt 的内容是:
Alice:90
Bob:85
运行:
cut -d: -f2 scores.txt
会得到:
90
85
这里的 -d: 表示使用 : 分隔每一行,-f2 表示输出分隔后的第 2 个字段。字段从 1 开始编号。
OJ 输入¶
真实的 cut 从命令行接收 -d:、-f2 等参数,再从文件或标准输入读取要处理的文本。OJ 只能向学生程序提供标准输入,不能为每组测试设置命令行参数,因此本题把两部分合并到一次输入中:
-d: -f2
Alice:90
Bob:85
学生程序需要按下面的方式读取:
- 第一行是
cut的参数。本例要求用:分隔并输出第 2 个字段; - 第二行开始是需要处理的文本。本例需要处理
Alice:90和Bob:85; - 第一行不是待处理文本,不能出现在输出中。
第一行中的参数以空白字符分隔,不含引号和转义。选项和值可以连写,也可以分开写,例如 -f2 与 -f 2 含义相同。程序必须从标准输入读取这些参数,不能使用 std::env::args()。
参数¶
| 参数 | 功能 |
|---|---|
-f LIST |
按字段选取 |
-d DELIM |
指定字段分隔符,默认为制表符 |
-b LIST |
按字节选取 |
-c LIST |
按字符选取 |
-s |
只输出含分隔符的行 |
LIST 的语法:
| 形式 | 含义 |
|---|---|
N |
单个位置,从 1 开始编号 |
N-M |
闭区间 |
N- |
从 N 到行尾 |
-M |
从行首到 M |
可用逗号分隔多项,例如 1,3-5,8-。
其他未提到的参数都不要求实现。
行为要求¶
以下几条是本题的重点,请确认你的实现全部满足。
- 使用
-f时,若某行不含分隔符,整行原样输出;若同时指定了-s,则跳过该行。 - 输出顺序按位置升序,与 LIST 中的书写顺序无关。例如对
a:b:c执行-d: -f3,1得到a:c,不是c:a。 - LIST 中的范围重叠时合并,不重复输出。例如对
a:b:c:d执行-d: -f1-2,2-3得到a:b:c。 - 行首或行尾的分隔符会产生空字段,空字段同样参与编号。
-b、-c、-f三者互斥,同时指定应报错退出。- LIST 为空或包含 0 应报错退出。
-s只在按字段操作时有意义,与-b或-c同用应报错退出。- 输入的数据部分只有一个空行时,仍应输出一个空行;数据部分完全为空时不输出。
错误处理只要求退出码非零,不要求错误信息与 GNU 版本逐字一致。
关于 -b 与 -c:-b 按字节计位置,可能切断多字节字符,输出的字节序列不一定是合法的 UTF-8;-c 按字符计位置。两者在纯 ASCII 数据上结果相同。
这几条大多不符合直觉
第 1、2、3 条尤其如此。它们是 cut 几十年来的实际行为,不是我们设计的陷阱。Agent 第一次生成的程序很容易在这些地方出错,请用后面介绍的方法逐一和 GNU cut 比较输出。
样例¶
输入:
-d: -f2
a:b:c
nodelim
:leading
trailing:
输出:
b
nodelim
leading
第二行不含分隔符,整行输出;第三行的第二个字段是 leading;第四行的第二个字段为空,因此输出空行。
下载材料¶
从课程文档仓库下载 lab3-materials-v1.zip。压缩包包含:
cut.c:GNU coreutils 9.11 的src/cut.c;cut.1.txt:同版本cutman page 的纯文本;COPYING和SOURCE.txt:许可证与来源说明。
文件的 SHA-256 为:
671844c01da6ccf560966b96ee60331b0981f62ca9b1952bf56b5688ef1c370f
若 Release 暂时无法下载,也可以从 GNU 官方获取完整源码:
curl -O https://ftp.gnu.org/gnu/coreutils/coreutils-9.11.tar.xz
完整源码中的目标文件是 coreutils-9.11/src/cut.c。完成作业只需阅读附件中的两个文件,不需要编译整个 coreutils。
评测环境¶
本题以 GNU coreutils 9.11 的行为为准。标准答案已经提前生成;OJ 评分时只运行你提交的程序并比较输出,不会在评测环境中调用 cut。
macOS 用户注意
macOS 自带的 /usr/bin/cut 不是本题采用的 GNU 版本。两者的许多常用功能相同,但不能保证所有边界情况完全一致。需要与本题采用的版本对比时,请用 Homebrew 安装 GNU coreutils:
brew install coreutils
安装后命令名是 gcut。请运行 gcut --version 检查版本;准备本题时 Homebrew 提供的是 GNU coreutils 9.11。比较输出时使用 gcut,不要把 macOS 自带的 cut 当作最终依据。
提交内容¶
- 在 OJ 上提交你的
.rs文件 - 在网络学堂作业中上传一个或多个已经检查、并在必要时完成脱敏的 Session JSON
文件命名见环境配置。
评分¶
| 项目 | 分值 |
|---|---|
| 五组数据(每组 0.4 分) | 2.0 |
| Session 文件完整 | 0.5 |
| 合计 | 2.5 |