2041_22T2.Q2

一、 读题与需求拆解

1. 数据结构分析:
输入数据通过标准输入 (< enrollments.txt) 传入,为标准的管道符 | 分隔文件,共 5 个字段。
例如:COMP1917|3360379|Costner, Kevin Augustus |3978/1|M

  • 字段 3 (Name):内部具有二级结构,格式为 [Surname], [First Names]
  • 字段 5 (Gender):标识性别,男性为 M

2. 目标输出:

  • 过滤条件:仅限男性 (male / M)。
  • 提取目标:仅提取姓氏 (Surname)。
  • 后处理:去重 (printed only once) 且按字母序排列 (alphabetical order)。

3. 硬性约束(Technical Constraints):

  • 必须是单一的 Shell pipeline。
  • 只能使用基础 UNIX 过滤器(如 grep, cut, sort 等)。

二、 技术路线设计

  1. 行级过滤 (Row Filtering):先用 grep 剔除无关行。
  2. 一级字段提取 (Primary Extraction):用 cut| 分割,提取包含姓名的整个第 3 列。
  3. 二级字段提取 (Secondary Extraction):改变分隔符,再次用 cut, 分割,精准剥离出姓氏。
  4. 排序去重 (Sorting & Deduplication):使用 sort 处理最终文本。

三、 最终脚本与逐级解析

命令实现:

1
2
3
#!/bin/dash

grep '|M$' | cut -d'|' -f3 | cut -d',' -f1 | sort -u

数据流逐级剖析:

  • grep '|M$'
    • 作用:精确过滤男性学生记录。
    • 原理:如果不加修饰直接使用 grep 'M',会误命中姓名或课程号中带有 M 的行(如 MaryCOMP3891)。使用 $ 锚定行尾,并带上前置分隔符 |,构成极严谨的正则表达式,确保只匹配最后一个字段确切为 M 的行。
  • cut -d'|' -f3
    • 作用:提取完整的姓名列。
    • 原理:指定分隔符为管道符 (-d'|'),提取第 3 个字段 (-f3)。此时数据流从完整的注册记录变为了纯姓名列表(如 Costner, Kevin Augustus)。
  • cut -d',' -f1
    • 作用:从姓名中剥离出姓氏。
    • 原理:由于数据规范中明确说明了姓氏由逗号分隔,此时动态切换定界符。指定逗号为分隔符 (-d',') 并提取第 1 个字段 (-f1)。截断逗号及其后方的所有字符,数据流此时仅剩姓氏。
  • sort -u
    • 作用:字典序排序并去重。
    • 原理sort 默认按 ASCII 字母表顺序对文本行进行排列。附加 -u (unique) 参数,等效于 sort | uniq 管道,在 O(N log N) 的排序过程中顺便完成 O(N) 的去重操作,满足输出规范要求。