目录

题目描述

195. 第十行

题意分析

给定文本文件 file.txt,只输出第 10 行。行号从 1 开始;空行同样占据一个行号,因为题目按物理行而不是非空记录计数。

文件可能不足 10 行。此时没有第 10 行,正确行为是不输出任何内容,不能退而输出最后一行,也不需要输出错误提示。

一旦读到并打印第 10 行,后续内容与答案无关,可以立即退出。相比只写 sed -n '10p' 后继续扫描到文件末尾,提前终止在大文件中更符合流式处理思路。

官方样例包含 Line 1Line 10,结果只应出现一行 Line 10,不能夹带其它行或调试信息。

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

核心思路

sed -n 关闭默认的逐行输出。地址 10 只让花括号中的命令作用于第 10 行:p 打印当前行,q 随即退出。

如果文件提前结束,地址 10 永远不会命中,pq 都不会执行,且由于 -n 已关闭默认输出,最终自然为空。

解题步骤

  • 使用 -n 禁止 sed 默认打印每一行。
  • 在第 10 行执行 p,只打印目标行。
  • 紧接着执行 q,避免继续读取无关的后续内容。

代码实现

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

复杂度分析

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

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

关键点总结

  • -np 必须配套:前者关闭默认输出,后者只打印目标行。
  • q 要和地址 10 放在同一个命令块中,否则可能在第一行就退出。
  • 行数不足时应零输出,这一点使 head | tail 的直观组合存在陷阱。
  • 目标行一旦找到就可以结束,体现 Shell 流式命令的短路意识。

解法二:awk 使用内建行号

核心思路

awkNR 是从输入开始累计的记录号。文本默认一行一条记录,所以在 NR == 10 时打印当前记录并 exit,语义与 sed 完全一致。

代码实现

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

复杂度分析

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

解法对比

写法 优点 注意点
sed -n '10{p;q;}' 最贴合“按地址选择一行”,命令短 需要同时理解 -npq
awk 'NR == 10 { print; exit }' 条件语义直观,容易扩展成复杂行过滤 == 不能误写成赋值

易错点总结

  • 使用 head -n 10 file.txt | tail -n 1:当文件只有 6 行时,它会输出第 6 行,而正确答案应为空。若使用该思路还必须先确认确有 10 行。
  • 写成 sed '10p' 而没有 -nsed 会默认输出全部行,并把第 10 行额外再打印一次。
  • 写成 sed -n '10p;q':不带地址约束的 q 会在处理第一行后退出,永远到不了第 10 行;应使用 10{p;q;}
  • 使用 tail -n +10:它会从第 10 行一直输出到文件末尾,而不是只输出一行。
  • 先过滤空行再计数:题目按原文件物理行号计算,删除空行会让后续行号整体前移。
  • 忘记提前退出sed -n '10p' 虽然答案正确,但仍会扫描超大文件的全部剩余内容;面试追问性能时应补上 qexit

相似题目

题目 难度 考察点
192. 统计词频 中等 多级管道处理全部文本并统计聚合
193. 有效电话号码 简单 用完整行正则筛选目标记录
194. 转置文件 中等 必须缓存字段并在 EOF 后重排输出