ARTICLE DETAIL

资讯详情

深耕郑州网站建设与运营推广的一线实战洞察。

Linux三剑客面试100题:grep、sed、awk高频考点深度解析

Linux三剑客面试100题:grep、sed、awk高频考点深度解析 带过不少新人也当过很多次面试官Linux 命令行这一关几乎是必考的。而在命令行里grep、sed、awk 这三兄弟又是绝对的主角。市面上讲三剑客的教程一抓一大把但真正能对着面试题把原理、用法、坑点讲透的很少。这套 100 道题是我结合 DeepSeek 做了一轮题目梳理再按照实际工作场景重新组织和校验过的结果覆盖了从基础匹配到日志统计分析再到复杂文本处理的完整链路。这篇文章不打算搞“题目列表简单答案”那种敷衍形式而是把 100 道题拆解成五个大模块每个模块挑出最有代表性的题目做深度解析顺带把面试官真正想考察的点也给你点透。不管你是准备面试的求职者还是带新人的老手或者单纯想把三剑客用得再溜一点的运维和开发这篇内容应该都能让你有收获。1. 先看题库整体100道题是怎么设计出来的1.1 难度梯度与题目分布拿到这 100 道题的第一件事不是闷头刷而是先看题目结构。我把整个题库按难度和主题做了个交叉分类大致分布如下表主题方向初级题了解命令中级题理解原理高级题综合实战合计正则表达式基础108220grep 文件匹配与过滤108321sed 流式编辑与替换810422awk 列处理与统计615829三剑客组合与shell集成2248合计364321100注意看 awk 的题量占了将近三分之一而且高级题里有一半落在 awk 上。这不是偶然。实际工作中grep 负责“找”sed 负责“改”awk 负责“算”但真正的统计、汇总、格式化输出这些硬骨头几乎都是 awk 在扛。面试官心里也清楚能把 awk 用得熟练的人对文本处理的理解基本不会差。再说难度梯度。36 道初级题主要考察“用没用过”比如grep -c是数行数还是数字符数sed s/old/new/g的 g 是什么作用awk -F怎么指定分隔符。43 道中级题考察“懂不懂原理”比如 grep 的 BRE 和 ERE 区别、sed 的模式空间和保持空间、awk 的 NR 和 FNR 差异。剩下的 21 道高级题基本是综合场景比如“统计 Nginx 日志里每个 IP 的访问次数 Top10”“把第二列和第三列互换并去掉重复行”之类。1.2 刷题的正确姿势很多人刷题是看一题记一题答案今天记住了明天换一个问法又懵了。我的建议是先建一个正则表达式的知识框架再分工具逐个击破。正则表达式是三剑客的公共地基。你可以在 Python、Perl 里写正则但 Linux 三剑客用的正则又有自己的变体基础正则BRE、扩展正则ERE、以及 PCREPerl 兼容正则。grep 默认走 BRE-E走 ERE-P走 PCREsed 默认也是 BRE-E可以切到 EREawk 则直接使用 ERE。不理解这层关系很容易出现“同样的正则在 grep 里能匹配到 awk 里就报错”的困惑。刷题的时候还有一个小技巧不要只看标准答案把答案的命令拆开每部分是什么含义去掉某个参数会怎样换成另一个工具能不能实现同样的效果。三剑客很多功能是重叠的比如“找包含某个关键字的行”grep、sed、awk 都能做到但各自适合的场景不同。把一道题用三种工具各写一遍你对它们的边界感会清晰很多。另外这套题的整理我给 DeepSeek 提了几个细化的要求比如“附上命令执行前后的对比”“易错点单独标注”“不要直接给答案先给思路”这些细节对于建立一个面试导向的复习体系很有帮助。AI 工具可以帮你批量生成题目和参考答案但最后一定要自己做一遍因为面试问答和实际敲命令是两码事。2. grep 高频题组匹配之外还有多少门道2.1 从最简单的匹配说起递归、排除与上下文很多人的 grep 水平停留在grep keyword file这远远不够。先看题库里的一道初级题题 7在 /var/log 目录下所有 .log 文件中递归查找包含ERROR的行并显示行号。grep -rn ERROR /var/log --include*.log-r是递归-n是显示行号--include限定文件类型。这三个参数是实际工作中最高频的组合没有之一。但注意-r和-R是有区别的-r在遇到符号链接时不会跟随-R会。如果你处理的日志目录里存在 symlink用-R才能查得全但也可能因为链接循环导致意外输出。再看一个容易答错的变体题 12查找包含success但不包含failed的行。这个需求听起来简单但实际处理很讲究。最简单的方式是管道grep success file | grep -v failed但如果你更熟悉 awk一条命令也能搞定awk /success/ !/failed/ file两道命令效果差不多但面试官考察点不一样。第一种考察的是-v反向匹配和管道组合思路第二种考察的是 awk 的多条件匹配能力。都写出来能体现你的灵活度。-v是 grep 的排除利器但真正的坑在于grep -v failed是排除包含failed子串的行而不是排除单词failed本身。如果你的日志里出现not_failed或者failed_xxx也会被排除。这种边界问题恰恰是面试题里最爱埋的雷。2.2 正则进阶BRE、ERE 与 PCRE 到底差在哪题库里有一道题特别能检验基本功题 23匹配手机号格式1 开头第二位 3-9总共 11 位数字分别用 grep 默认语法和 grep -E 写出。默认 grep 走 BRE花括号表示次数必须转义grep -n ^1[3-9][0-9]\{9\}$ phones.txt而grep -E走 ERE花括号不需要转义grep -nE ^1[3-9][0-9]{9}$ phones.txt这道题的考点有两个。一是你是否清楚 BRE 和 ERE 在元字符转义上的差异BRE 里?、、{、}、(、)这些字符默认是字面含义要表示特殊含义必须加反斜杠ERE 恰好相反这些字符默认就是特殊含义加反斜杠反而表示字面字符。二是你是否知道^和$表示行首行尾这是做整行匹配的前提。再进阶一点PCRE 支持\d、\w这种更简洁的写法所以有些面试者会直接写grep -P ^1[3-9]\d{9}$ phones.txt-P参数确实好用但它依赖 PCRE 库而且在高版本的 grep 里依然不是默认选项。在部分精简版系统或嵌入式环境里-P可能不可用。面试时如果写-P最好顺带说一句“这是 PCRE 扩展语法某些环境需要额外支持”显得你心里有数。2.3 实战案例日志与配置处理中的 grep题库里的高级 grep 题基本都挂在场景上比如题 41从 access.log 中提取所有返回状态码为 500 的行并统计数量。这个需求 grep 只能做一半提取行可以统计数量要交给wcgrep 500 access.log | wc -l这里有个细节为什么要写成 500 而不是500因为日志里可能有5000、1500这种字段加前后空格是为了锚定独立的状态码字段。更严谨的做法是把响应码放到行尾匹配比如grep 500$具体要看你的日志格式。面试时能主动讲出这个细节比死记命令要加分得多。再举一个常见组合提取 IP 并排序去重。grep -oE ([0-9]{1,3}\.){3}[0-9]{1,3} access.log | sort | uniq -c | sort -rn-o只输出匹配到的部分而不是整行sort | uniq -c统计每个 IP 出现次数最后的sort -rn按次数从大到小排。这条命令是面试经典题背下来不难但能解释清楚-o的作用才算真懂。关于 grep我还有一个建议日常工作中不要只依赖 grep 的默认行为。--colorauto让匹配结果高亮排查问题的时候非常直观-A、-B、-C可以输出匹配行的后文、前文和上下文配合日志中的堆栈信息特别好用。这些参数看似零碎但面试题里经常以“怎么写更高效”的形式出现。3. sed 高频题组流编辑器的三板斧3.1 替换操作定界符、转义与分组引用sed 最核心的能力就是替换。先看一道初级题题 18把文件里所有的foo替换为bar并直接修改原文件。sed -i s/foo/bar/g file.txt三个关键点。一是-i直接修改文件但-i的写法在不同 sed 版本里有差异Linux 的 GNU sed 直接加-imacOS 的 BSD sed 需要-i 。二是s是替换命令g是全局替换不加g的话每行只替换第一个匹配。三是foo里的/如果换成路径比如替换/usr/local为/opt定界符就要改写成sed -i s#/usr/local#/opt#g file这样可以免去大量转义。面试官很喜欢在分组引用上出题题 26把2024/01/05格式的日期转换成2024-01-05。sed -E s#([0-9]{4})/([0-9]{2})/([0-9]{2})#\1-\2-\3#g file这个解法的核心是()分组和\1引用。注意-E参数它让 sed 进入 ERE 模式这样{}和()都不需要转义。如果你不用-E就得写成\([0-9]\{4\}\)可读性差很多也容易写错。这里有个易错点必须提醒捕获组是从(出现的顺序编号的\1是第一个左括号对应的内容。如果正则前面还有其他分组编号会顺延写错\1、\2的顺序是新手最常见的问题。我建议在本地调试的时候先不加-i让 sed 输出到屏幕确认无误后再加-i写回文件。3.2 地址匹配与范围控制sed 的地址匹配是另一个高频考点题 33只删除文件第 10 行到第 20 行的内容。sed 10,20d filed是删除命令。这个题简单但很多人不理解10,20d中的逗号其实是一种“范围地址”的写法它的规则是从匹配到第一个地址开始到匹配到第二个地址为止。范围不限于数字也可以混合正则sed /BEGIN/,/END/d file这条命令会删除从匹配BEGIN的行开始到匹配END的行结束的所有内容。这种“区间删除”在清理配置文件片段、移除日志中的异常段时非常有用。还有一道容易答错的题题 35打印文件第 1 行到第 5 行但不修改文件。很多人的第一反应是sed -n 1,5p file。-n关闭默认输出p命令显式打印。如果忘了-n结果会非常难看sed 默认会打印所有行而匹配到的行会被打印两次。所以sed的-n和p基本是绑定出现的考试时只要看到p先检查有没有-n。3.3 处理配置文件与日志流的经典场景题 52把 Nginx 配置里listen 80;全部改成listen 8080;同时备份原文件。sed -i.bak s/listen 80;/listen 8080;/g nginx.conf-i.bak的意思是先备份为nginx.conf.bak再执行替换。生产环境改配置一定要养成备份的习惯这个参数就是为此设计的。如果你想更稳妥可以先执行sed s/listen 80;/listen 8080;/g nginx.conf查看输出确认无误后再加-i操作。sed 还可以直接处理管道流这是它“流编辑器”称号的来源tail -f app.log | sed s/ERROR/【错误】/这个用法在处理实时日志时很实用不改原文件只修改输出让日志里的关键字更醒目。面试时如果能主动说“sed 最大的特点是流式处理所以它很适合在管道中充当文本修改器”会比单纯背命令更有深度。sed 的难点其实不在命令本身而在于“模式空间”这个概念。很多人不理解sed每一行是独立处理的跨行操作要用N、H这些多行命令。面试题里如果出现“把两行合并成一行”“跨行替换”这类需求基本都是考察模式空间和保持空间的配合。题库里这类题目偏难我建议先把单行处理练熟再研究N和H因为大多数实际需求用单行操作就能解决。4. awk 高频题组文本处理的“重武器”4.1 字段分割与内置变量awk 的处理模型是“按行读入按列切分”。这个模型是理解 awk 一切特性的基础也是它和 grep、sed 最本质的区别。题 22打印 /etc/passwd 中每个用户的用户名和登录 shell分隔符是冒号。awk -F: {print $1, $7} /etc/passwd-F:指定冒号作为字段分隔符$1是第一个字段$7是第七个字段。看起来简单但背后的机制值得展开awk 默认分隔符是空白空格或 Tab-F可以临时指定。如果你在脚本里需要频繁切换分隔符也可以在 BEGIN 块里设置awk BEGIN{FS:} {print $1, $7} /etc/passwd这两种写法等价但BEGIN{FS:}更灵活因为它只是赋值给内置变量FS你甚至可以在处理过程中改变 FS 的值让不同的行用不同的分隔符解析。再嵌套一题题 29统计当前目录下所有 .log 文件的总行数。一个常见解法是cat *.log | wc -l但 awk 也能做而且能统计得更细awk {count} END{print count} *.logcount每读一行执行一次END块在文件全部处理完后执行。count是没有预先声明的变量awk 默认把它当数字用初始值是 0。这种“未声明直接使用”的特性使用起来很方便但也容易踩坑——如果你拼错变量名awk 不会报错只会默默给你一个错误结果。4.2 条件、循环与数组统计awk 的真正威力在于它是一门“微型语言”。题库里这道题是绝对的高频题 48统计 access.log 中每个 IP 的出现次数并按次数降序输出前 10 个。awk {count[$1]} END{for (ip in count) print count[ip], ip} access.log | sort -rn | head -10很多人会背这条命令但面试官更想听你解释三个阶段读入阶段逐行执行{count[$1]}用 IP 作为数组下标累加计数文件读完进入 END 阶段用for (ip in count)遍历数组输出结果后交给sort -rn排序head -10取前 10。count[$1]这种写法是 awk 做频次统计的核心模式可以套用到几乎所有分组统计场景比如按状态码统计、按用户统计、按时间分钟统计等。再进阶一点题 55求第二列数值的平均值保留两位小数。awk {sum$2; n} END{printf %.2f\n, sum/n} data.txtprintf是 awk 里格式化输出的函数%.2f表示保留两位小数。如果数据文件是空的n 等于 0直接sum/n会得到一个无穷大或报错健壮性好的写法应该加上n0的判断这是大数据量脚本里容易忽视的问题。awk 的数组有一点和普通语言不同它的下标可以是字符串本质上是一个关联数组。这个特性让它做分组统计特别自然。比如统计每种状态码的占比awk {code[$9]} END{total0; for (c in code) totalcode[c]; for (c in code) printf %s %.2f%%\n, c, code[c]/total*100} access.log这种题目已经属于高级范畴考察的不只是 awk 语法还有你设计统计流程的思路。建议在纸上画一画先累加再遍历再计算百分比思路清楚了代码自然就出来了。4.3 多文件处理与 shell 变量传参awk 可以一次处理多个文件而且内置变量FNR和NR的区别是面试必问题题 60有两个文件 a.txt 和 b.txt希望分别打印各自的行号。awk {print FILENAME, FNR, $0} a.txt b.txtFNR是当前文件内的行号NR是所有已读入行的总行号。如果文件 A 有 5 行文件 B 有 3 行读到 B 的第一行时FNR是 1NR是 6。这个区别在合并多个文件做去重时特别重要。再一个常见场景是 awk 如何接收 shell 变量题 68用 shell 变量 name 作为 awk 的匹配条件打印包含该变量的行。nameAlice awk -v n$name $0 ~ n file.txt-v选项可以把外部变量传入 awk在 awk 内部使用n来引用。如果不加-v直接写成awk $0 ~ $nameawk 会把$name理解成第 name 个字段这是完全不同的含义。还有一个陷阱如果变量名是FS或OFS这种内置变量名用-v传入会改变 awk 的内置行为需要特别注意。awk 的坑多在细节。$0表示整行$NF表示最后一个字段这两个符号也经常在题里出现。NF是当前行的字段数量$NF是取值两者差一个美元符含义天差地别。面试时如果把$NF说成“字段数量”基本就凉了。5. 综合高频题与易错点三剑客的组合艺术5.1 三剑客各司其职的经典套路实际工作中三剑客很少单独出现组合使用才是常态。有一道经典综合题题 82从 Nginx 日志中找出返回状态码为 502 的请求提取出对应的 URL并统计每个 URL 出现的次数。这道题需要三个工具协作完成grep 502 access.log | awk {print $7} | sort | uniq -c | sort -rngrep先过滤出包含 502 的行awk {print $7}提取第 7 列Nginx 日志默认格式里$7是请求 URLsort | uniq -c统计每个 URL 的次数再sort -rn排序。这条命令是“先筛、后取、再统计”思路的典型代表四个阶段各自由最合适的工具完成。更复杂的场景是 grep 和 awk 配合做条件过滤。比如筛选出访问次数超过 100 的 IPawk {count[$1]} END{for (ip in count) if (count[ip]100) print count[ip], ip} access.log | sort -rn这个需求 grep 无法单独完成因为“次数超过 100”是一个聚合条件需要 awk 先把数据算出来再用if判断。这种多阶段处理思路比单条命令背诵重要得多。5.2 面试官最爱挖的坑三剑客的面试题里有很多隐蔽的坑我总结几个高频出现、学员错误率最高的第一个坑是grep -c到底统计什么。grep -c统计的是匹配的行数而不是匹配的次数。如果一行里出现了 5 次ERRORgrep -c ERROR只会计数 1。想统计出现总次数要用grep -o ERROR | wc -l-o把每次匹配单独输出一行再数行数。第二个坑是 sed 的符号。在 sed 的替换内容里表示“整个匹配到的内容”所以sed s/foo/()/g会把所有foo替换成(foo)。如果你确实想替换成字面意义的需要写成\很多人在替换 XML 实体或包含连接符的文本时踩过这个坑。第三个坑是 awk 的print和printf混用。print是简化输出字段之间用OFS默认空格连接自动换行printf是完全格式化输出不会自动换行。两者混用时输出会粘在一起非常容易出错。第四个坑是正则里的贪婪匹配与非贪婪匹配。grep 和 sed 默认都是贪婪匹配sed s/.*//g会把一整段标签内容全部删掉而不是只删第一个标签。Perl 风格的非贪婪在 grep-P里可以用.*?但 BRE/ERE 本身没有非贪婪的概念。这个点经常出现在需要清洗 HTML 或配置模板的面试题里。三剑客组合还有一条通用经验能用管道解决的问题不要写复杂的单条命令反之亦然。管道让数据流清晰可见每一步都能单独验证调试成本低很多。我在生产环境里排查问题基本都是一条一条命令串起来每步用head看几条输出确认无误再拼成完整管道。6. 常见问题与排查技巧实录6.1 高频报错与执行结果异常把我在教学和实际工作中遇到的高频问题整理成了一张速查表现象可能原因排查与解决sed: -e expression #1, char X: unknown option to s替换内容中包含了定界符如/更换定界符如s#old#new#ggrep: invalid option -- r部分环境 grep 版本或别名导致参数解析异常用grep --help查看当前版本支持参数确认命令格式awk 输出为空$n中的 n 超出了字段数量范围先用awk {print NF} file打印每行字段数awk 统计结果明显偏大count[$1]的下标字段选错比如$1不是预期的 IP先awk {print $1} file | head查看字段内容sed 使用-i后文件权限变化部分 sed 实现是通过重写新文件来完成的修改后检查属主和权限必要时用chmod恢复grep 匹配中文内容失败系统 locale 未设置为 UTF-8检查LANG环境变量临时用LANGen_US.UTF-8这张表里的问题都是我实际踩过或者学员问过的。第一个“未知选项”几乎每天都能在群里看到原因极其简单就是替换内容里有/但多数人第一反应是“sed 是不是坏了”。所以我把这个排最前面。6.2 几条压箱底的调试经验最后分享几个让我少走弯路的经验都是文档里不会写的东西。第一调试时永远先不加-i。无论 sed 还是其他修改文件的命令先让结果输出到终端肉眼确认后再加上-i。很多人在-i后才发现替换结果不对原文件已经改坏了只能从备份里恢复。如果有备份还好没有备份就只能干瞪眼。第二awk 脚本从简单开始逐步加条件。我见过太多人一上来就写一个庞大的 awk 脚本报错了却不知道是哪一步出了问题。正确的做法是先用awk {print $1}看看字段对不对再加匹配条件再加上统计逻辑最后加格式化输出。每一步都验证比整体调试高效得多。第三用好head和管道配合。处理超大日志文件时别一上来就全量跑先用head -100 file | 你要调试的命令确认逻辑没问题再全量执行。这个习惯能帮你省下大量等待时间也能避免一条错误命令在全量文件上产生毁灭性影响。第四grep、sed、awk 不是互相替代的关系。很多人在掌握了 awk 之后恨不得所有文本处理都用 awk 搞定。实际上能一条 grep 解决的事情就不要写一段 awk能一条 sed 完成的事就不要引入数组。命令越简单出错概率越小别人接手也更容易看懂。这一点我觉得比掌握所有高级语法更重要。第五面试时如果被问到不会的题目不要直接说不会。把你能想到的方向说清楚比如“这个需求我会用 awk 的数组来统计但是具体输出格式我需要再确认一下”面试官至少知道你有解题思路。三剑客本质上都是工具思路清晰的人就算某个参数记不准看一眼 man page 也能写出来思路混乱的人就算背了一百道题碰到新场景还是懵。这也是我整理这套题库时最强调的部分。这套 100 道题覆盖的知识点足够应对绝大多数 Linux 岗位面试了但请你记住背答案只是底线能把每条命令拆开讲清楚为什么才是真正的分水岭。希望你刷完题后不只是“见过”而是真正“会用”。
返回列表