题目重点:题目要求找出文件中包含目标子串的行,并考虑 flag 扩展;将解析、规范化、匹配和输出分层。
题意与假设
这道练习题保留了面经中值得训练的核心约束,并将需要澄清的条件单独列出。现场拿到变体时,先和面试官确认这些条件。
- 训练版输入为已拆好的行序列与 literal 子串;示范 ignore_case 和 line_numbers 两项选项,不当作题目指定 flag。
- 大小写忽略用 Unicode casefold;若真实题目按字节/ASCII 匹配,语义和性能需另定。
解题路线
- 先给最小核心函数 match(line,needle,options),逐行保留原顺序和原文本。
- 命令行 parser 把 flag 转成结构化 options,再由 matcher 处理 case/regex 等匹配规则,formatter 负责行号与输出;新增 flag 不在主循环里嵌套大量条件。
- 先区分 literal substring 与正则表达式;题目只说包含字符串,不能擅自用 regex。
- 若文件很大,按行迭代避免一次性加载;输出亦可 yield 流式生成,遇解码错误要约定策略。
手动走一遍
训练行 [‘Ab’,‘ba’,‘xx’] 搜 ‘a’:大小写敏感仅命中 ‘ba’;ignore_case 后命中前两行;加行号可输出 ‘1:Ab’,‘2:ba’。选项仅用于演示扩展层。
Python 参考实现
下面的代码按上文假设实现,适合本地运行并追加自己的测试用例。
代码区可横向滚动;使用键盘时,先聚焦代码区再按方向键查看。
def grep_lines(lines, needle, *, ignore_case=False, line_numbers=False):
"""Return matching lines, optionally prefixed by 1-based line numbers."""
if ignore_case:
needle = needle.casefold()
result = []
for number, line in enumerate(lines, 1):
haystack = line.casefold() if ignore_case else line
if needle in haystack:
result.append(f"{number}:{line}" if line_numbers else line)
return result
复杂度
L 行总字符数 N,直接子串查找典型近 O(N) 但最坏取决于底层算法/模式长度;逐行流式额外内存与最长行及输出缓存有关。
易错点与追问
容易失分的边界
- 把具体 -i/-n 说成题目已给。
- 对整个文件读入 split 导致大文件内存增长。
- 返回规范化后的行而丢原文大小写。
- 把 literal pattern 误作 regex。
继续深挖
- 新增 whole-word 或正则 flag 如何不破坏核心?
- 超大文件如何流式处理?
- 多文件并行输出如何保持顺序?
