SDE · Technical Coding

Bloomberg 简化 Grep:行匹配、Flag 解析与可扩展结构

题目要求找出文件中包含目标子串的行,并考虑 flag 扩展;将解析、规范化、匹配和输出分层。

题目重点:题目要求找出文件中包含目标子串的行,并考虑 flag 扩展;将解析、规范化、匹配和输出分层。

题意与假设

这道练习题保留了面经中值得训练的核心约束,并将需要澄清的条件单独列出。现场拿到变体时,先和面试官确认这些条件。

  • 训练版输入为已拆好的行序列与 literal 子串;示范 ignore_case 和 line_numbers 两项选项,不当作题目指定 flag。
  • 大小写忽略用 Unicode casefold;若真实题目按字节/ASCII 匹配,语义和性能需另定。

解题路线

  1. 先给最小核心函数 match(line,needle,options),逐行保留原顺序和原文本。
  2. 命令行 parser 把 flag 转成结构化 options,再由 matcher 处理 case/regex 等匹配规则,formatter 负责行号与输出;新增 flag 不在主循环里嵌套大量条件。
  3. 先区分 literal substring 与正则表达式;题目只说包含字符串,不能擅自用 regex。
  4. 若文件很大,按行迭代避免一次性加载;输出亦可 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 如何不破坏核心?
  • 超大文件如何流式处理?
  • 多文件并行输出如何保持顺序?
✓已复制微信号!