题目描述

✅ 195. 第十行

image-20260928233528939

题意分析

从文本文件 file.txt 中只输出第 10 行,行号从 1 开始。空行也占一个行号,不能先删除空行或按单词数量计数。

文件不足十行时,没有对应的目标行,应当没有任何输出;不能改为输出文件最后一行。找到第十行之后,后续内容不再影响答案。

解法一:sed 按地址打印并退出

核心思路

[!blue]

sed 会逐行读取文本,默认在每一轮结束时打印当前内容。这里先用 -n 关闭自动打印,让是否输出完全由后面的显式命令决定。

地址 10 只匹配第十行,后面的 {p;q;} 把打印与退出绑定到同一个地址:命中后先用 p 输出这一行,再用 q 结束处理。前九行没有打印动作,第十行也只打印一次。

若文件提前结束,地址始终没有命中;自动打印又已经关闭,所以自然没有输出。退出放在命中目标的命令块中,既不会提前结束,也不需要继续读完整个大文件。

解题步骤

  1. 用 -n 关闭默认输出。
  2. 在地址 10 的命令块中执行 p,打印目标行。
  3. 紧接着执行同一块中的 q,结束处理;未读到第十行就遇到文件末尾时不输出。

代码实现

sed -n '10{p;q;}' file.txt

复杂度分析

设从文件开头到第 10 行末尾(若不足 10 行则到 EOF)的字符数为 $K$,最长单行长度为 $L$。

  • 时间复杂度:$O(K)$,最多扫描到第 10 行即退出;若文件不足 10 行,则扫描整个文件。
  • 空间复杂度:$O(L)$,sed 只需保存当前模式空间,相对整个文件是流式常量空间。

关键点总结

[!green]

  • -n 负责取消默认输出,p 负责只输出目标,两者缺一不可。
  • 地址同时约束打印和退出,保证读到第十行才执行这两个动作。
  • 不足十行时没有命中,零输出不需要另设分支。

解法二:awk 使用内建行号

核心思路

[!blue]

awk 默认按换行分隔记录,内建变量 NR 随每条记录递增,从 1 开始,空行也会计入。因此条件 NR == 10 恰好选中原文件第十行。

命中时不带参数的 print 输出当前整条记录,而不是只输出某个字段;随后 exit 立即结束。没有命中时这条规则没有动作,也不会自动打印其他行。

文件不足十行,条件始终为假,结果自然为空。它与 sed 解法利用的是同一个过程:逐行计数,只在目标位置打印并停止。

解题步骤

  1. 使用默认记录分隔符按行读取,让 NR 自动累计行号。
  2. 仅在 NR == 10 时执行规则,打印当前完整记录。
  3. 同一规则中执行 exit,不再扫描目标之后的内容。

代码实现

awk 'NR == 10 { print; exit }' file.txt

复杂度分析

  • 时间复杂度:$O(K)$,读取到第 10 行或 EOF。
  • 空间复杂度:$O(L)$,只缓冲当前记录。

关键点总结

[!green]

  • NR 从一开始计数,比较应写成 ==,不能写成赋值。
  • 不带参数的 print 打印整条记录,保留这一行的内容。
  • 条件打印与退出放在同一规则内,保证不足十行时不会输出替代结果。

易错点总结

[!yellow]

  • head -n 10 | tail -n 1 在不足十行时仍会输出最后一行,不符合本题的零输出要求。
  • sed 忘记 -n,会默认打印全部经过的行,并让显式 p 再输出目标行一次。
  • 写成 sed -n '10p;q',无地址约束的 q 会在第一行就执行,应将两条命令一起放入地址块。
  • tail -n +10 输出的是从第十行直到末尾的全部内容,不是仅一行。
  • 先过滤空行会改变后续行号,查询的就不再是原文件第十行。
  • awk 把 NR == 10 写成 NR = 10,会修改变量而不是筛选目标记录。

相似题目

题目 难度 关联与区别
193. 有效电话号码 简单 同样以行作为处理单位;本题按行号筛选,电话号码筛选改用正则条件,可对照 awk 的条件与输出规则。
转载与许可
作者
链接 https://hgnulb.github.io/blog/2026/50498851
许可 本博客所有文章除特别声明外,均采用 CC BY-NC-SA 4.0 许可协议,转载请注明出处!