很多人问我,Linux岗位面试到底最看重什么。我的答案始终是同一个:先看Shell三剑客,也就是grep、sed、awk这三个命令掌握得怎么样。这个结论不是面试官拍脑袋想出来的,而是实际工作需求决定的——日志排查、批量文本处理、数据统计、脚本自动化,哪一样都离不开这三个命令。我整理过一套100道三剑客面试题并附上详细答案,起初是想给自己带的实习生做考核用,后来发现这套题库几乎覆盖了市面上大部分Linux面试考察点。今天把核心知识点和典型题目拆开聊聊,重点讲清楚考点背后的原理、常见的坑以及怎么答才能让面试官眼前一亮。
我利用DeepSeek辅助做过一轮题目生成和答案校验,说实话,AI能帮忙把题目体系搭得很完整,但真正有价值的细节——比如某个命令在什么版本下行为不一致、哪种写法在生产环境会酿成大错——这些还是得靠实际踩坑经验来补。下面按grep、sed、awk三个部分展开,每个部分都会结合高频面试题和真实使用场景来讲。
1. 面试题库设计思路:三剑客到底在考什么
1.1 三剑客的定位差异
先搞清楚三剑客各自的定位,这是面试题的基础逻辑。grep负责“查”,在文件或流中过滤出匹配指定模式的行;sed负责“改”,对文本流进行增删改替换;awk负责“算”,按字段对文本进行切分和统计。三者之间有交集,但侧重点完全不同。
实际面试中,很多候选人的问题就是混淆了这三者的边界。例如问“怎么统计一个文件有多少行”,有人上来就写grep -c '',这虽然能数出非空行数量,但没理解grep的本质是模式匹配。正确的做法有很多,sed -n '$='可以直接输出行号,awk 'END{print NR}'则利用NR自动记录处理过的记录数,这两个方案都比grep更契合“统计行数”这个需求。
我在设计题库时,将100道题按照grep约30道、sed约30道、awk约35道、综合组合题约5道来分配。不是为了凑数,而是为了覆盖不同层面的能力:grep考察正则基本功,sed考察地址定址和编辑命令的熟练度,awk考察编程逻辑和数据统计思维。组合题则是模拟真实运维场景,考察能否把三个命令融会贯通。
1.2 100道题的知识点分布
一个合格的三剑客考题库,需要覆盖以下核心模块:正则表达式基础(字符类、锚点、量词、分组)、选项参数的理解、地址范围的运用、模式空间与保持空间、内建变量的含义、数组统计、真实场景的日志分析。
正则这一块,我认为是最容易被忽略又最致命的。很多人在网上抄了各种正则写法,却分不清grep默认的BRE(基础正则)和-E参数启用的ERE(扩展正则)有什么区别。比如在BRE下,括号必须写成( )才能表示分组,而在ERE下直接写( )就行。如果面试官让你匹配一个重复出现的单词,你能准确写出grep -E '([a-zA-Z]+) \1'才算真正理解了分组和反向引用。这个题目我放在题库的前置位置,就是为了快速筛掉基本功不牢的人。
选项参数方面,grep的-o、-E、-i、-v、-c、-l、-r、-A、-B、-C这些都是必考项。sed的-n、-i、-e、-f是基础。awk的-F、-v等也经常出现。每个选项都要知道“为什么不加它就不行”,单纯背命令是应付不了追问的。
2. grep:把高频用法和正则吃透
2.1 面试必问的grep选项
面试中grep的出场率极高,但考得很细。最经典的几个:
grep -v:反向匹配,过滤掉指定模式的行。比如查看配置文件时想排除注释行和空行,很多人写grep -v '#',但这样会把行中间有#的内容也过滤掉,正确写法要配合锚点:grep -v '^#' file | grep -v '^$'。这个组合在面试中出现的频率非常高,问的就是你对行首行尾锚点的理解。
grep -E:扩展正则在复杂匹配中几乎是必须的。比如匹配手机号或IP地址,用基本正则写起来会很别扭。面试常考的IP匹配:grep -E '^([0-9]{1,3}.){3}[0-9]{1,3}$',这个写法能匹配形如192.168.1.1的字符串,但不校验数字范围是否合法(比如999.999.999.999也能通过)。如果面试官追问怎么精确校验,这是一个加分点。
grep -c:统计匹配行数。注意它统计的是行数而不是匹配次数,每行只计一次。如果一行里有多个匹配,grep -c照样只算1。需要统计出现次数时,要用grep -o pattern file | wc -l,这个区别是高频考点,也是很多人踩坑的地方。
grep -o:只输出匹配到的部分而不是整行。这在事后处理中非常有用。比如从一个日志行中抽取所有IP:grep -oE '([0-9]{1,3}.){3}[0-9]{1,3}' access.log,输出结果是一行一个IP,方便后续用sort和uniq做统计。这也是一个组合题的基础。
grep -n/-A/-B/-C:-n显示行号,-A显示匹配行的后几行,-B显示前几行,-C显示前后几行。日志排查时我最常用grep -C 5 'ERROR' app.log,直接看错误上下文,不用再来回cat和grep好几次。
这里提醒一下,grep处理大文件时不要直接grep然后切换到其他命令,能用--include和--exclude限定范围就不要全盘扫描。grep -r在目录里递归搜索时,加上--include='*.log'能显著提升效率。面试时主动说出这类性能优化的点,会让人觉得你有真实运维经验。
2.2 grep正则经典题拆解
正则部分是grep面试的重头戏。我挑几个题库里最典型的题展开。
第一道:匹配空行。最简单的写法是grep '^$' file。但有面试官会故意把问题改成“怎么去掉空行”,答案应该是grep -v '^$' file。注意这个模式只匹配“空行”,也就是行内没有任何字符的行。如果一行有空格或制表符,它不算空行,得写成grep -v '^[[:space:]]*$'才行。这个细节我很喜欢考,因为它区分了只会背命令的人和真正理解正则的人。
第二道:匹配以数字开头的行。简单写法:grep '^[0-9]' file。扩展写法:grep '^[[:digit:]]' file。如果要求至少一个数字,得用grep -E '^[0-9]+'。这里有个常见错误,很多人以为在BRE下+也代表“一个或多个”,其实在BRE下+就是个普通字符,只有在ERE(加-E)下才是量词。面试答到这里,主动补充“BRE和ERE的区别”,属于会让面试官点头的操作。
第三道:匹配连续重复的单词。grep -E '([a-zA-Z]+) \1' file。\1代表匹配第一个括号的内容,这种反向引用考察的是一种语言特性,不只是命令用法。我经常把这道题作为“能不能进下一轮”的分水岭。有些候选人能背出所有选项参数,但一遇到需要组合正则表达式的题目就卡壳,说明平时没有真正做过文本分析。
2.3 grep答题时的三个坑
从经验来看,grep相关面试题有典型的三个坑。
第一个坑:忘了加引号。正则里面包含*或?等特殊字符时,不加引号会被shell解释成通配符。比如grep *.txt含义完全不是你想的那样。面试时如果手写代码,一定要习惯把正则用单引号包起来。
第二个坑:区分不清grep和find的职责。grep查的是文件内容,find查的是文件名。面试官问“在多级目录下查找所有包含error的.py文件”,很多人上来就find -name "error",这查的是文件名,正确思路是find . -name ".py" | xargs grep -l 'error'或grep -rl --include='.py' 'error' .。这个考点在泛运维岗位中尤其常见。
第三个坑:grep -E和egrep的关系。egrep是grep -E的远古别名,很多老资料还在用,但在现代脚本里不应该出现。如果你在面试中主动说“我可以用egrep”,在某些较真的面试官眼里等于暴露了知识体系陈旧。
3. sed:理解流编辑的核心逻辑
3.1 sed工作流程与模式空间
sed面试题和grep有一个本质区别:grep是纯查询,sed涉及修改输出流,所以理解它的工作流程尤其重要。sed逐行读取文件到模式空间(pattern space),执行编辑命令,然后输出模式空间的内容,再读取下一行,如此循环。
搞清楚这个流程后,“为什么sed默认会把没改过的行也输出”这个问题就迎刃而解了。我刚带新人时,经常有人问:我只想打印第10行,为什么awk第10行的前后行也被打出来了?这就是不理解默认输出逻辑。正确做法是加-n参数,-n的作用是抑制默认输出,只输出被p命令明确标记的行。
关于保持空间(hold space),这是进阶考点。保持空间是sed的另一个缓冲区,可以把数据暂存起来供后续行使用。最经典的题目是反转文件行序:sed '1!G;h;$!d' file。这个命令咋一看很吓人,拆开来看:1!G表示除了第一行外,把保持空间的内容追加到模式空间;h表示把当前模式空间存入保持空间;$!d表示除了最后一行外删除模式空间内容。最后一行的模式空间自然包含所有累积内容,输出后就是反转效果。
这种题面试中不常考,但一旦考了,就是压轴级别。能答出来的人,基本可以判断源码级理解水平。如果只是背命令,面试官追问两句必然露馅。
3.2 sed高频题:定址、增删改查
sed的核心语法是sed 地址 编辑命令。地址可以是行号、正则、范围。我整理几个考得最多的。
打印第N行:sed -n '10p' file。这是最简单的定址,考察点为-n的配合。稍微变形一下是“打印第10到第20行”:sed -n '10,20p' file。再变形是“每隔两行打印一行”:sed -n '1~3p' file,这里~表示步进,1~3代表从第1行开始,每3行取1行,即第1、4、7行。
删除空行和注释行:sed '/^$/d; /^#/d' file。分号表示多条命令顺序执行。注意这里d命令直接删除整行并且不会继续后续命令。如果想同时删掉行尾的空格,要写成sed 's/[[:space:]]*$//',这是另一个考点了。
替换文件中的字符串:sed -i 's/old/new/g' file。-i是原地修改,g表示全局替换每一行中的所有匹配。这里有个很重的坑我建议面试一定要提:如果一行里有两个old,不加g只会替换第一个。实际生产修改配置时,漏掉这个g就可能酿成线上事故。
删除指定行号范围之后的所有行:sed '5,$d' file,表示删除第5行到文件末尾。
在指定行前后插入内容:sed '3i insert text' file(在第3行前插入),sed '5a add text' file(在第5行后追加)。i和a命令处于配邻命令。这种题目常出现在“写一段脚本自动修改Nginx配置”之类的场景中。
sed面试还有一个高概率考点:sed -i在不同系统的行为差异。GNU sed(Linux上常见)里,sed -i直接原地修改。而macOS自带的BSD sed里,-i必须跟一个扩展名参数,比如sed -i '' 's/a/b/' file,否则语法不通过。这道题我会单独拿出来问,因为很多从Mac本地环境转到Linux服务器上跑脚本的人都在这里翻过车。
3.3 sed进阶题的答题思路
进阶题通常会涉及到替换反向引用和范围模式。比如“将每一行的前三个字符用[xxx]包起来”,答案:sed 's/^(...)/[\1]/' file。考察点是BRE下的分组写法( )和反向引用\1。如果写成'^(...)',在BRE下括号会被当成普通字符,匹配不出来。只有在加-r或-E参数启用ERE后才可直接用( )。
“从匹配A的行到匹配B的行之间做替换”这类题目也很多。比如在ERROR块内把level=INFO改成level=DEBUG:sed -i '/ERROR/,/END_ERROR/ s/level=INFO/level=DEBUG/' file。这是定址范围和替换命令的结合,考察对sed多命令组合的理解。
我在题库里特意放了一道原理解析题:“sed如何实现取某一段内容复制到文件末尾”。思路是先用/pattern/地址把目标行找到,再用w命令写入目标文件,最后通过r命令把目标文件内容读入。这道题看起来复杂,实际拆开后就是两个基础命令的组合。答这类题时,建议面试时把自己的思考步骤说清楚,先定址、再选择命令、最后考虑要不要加-n和-i,这样即使最终答案有偏差,面试官也能看出你的分析框架是成立的。
4. awk:比想象中更强大的数据统计工具
4.1 awk核心变量与执行流程
awk的面试题是整个三剑客知识体系里最深的部分,因为它的编程语言属性和行处理模型远比grep和sed复杂。awk的执行流程是BEGIN块、逐行处理主块、END块。BEGIN块在处理任何输入前执行,常用于初始化变量和设置分隔符。主块对每一行执行一次,END块在所有行处理完后执行,常用于汇总输出结果。
有个高频题:怎么理解NR和FNR的区别。NR是所有输入文件累计处理的行号,FNR是当前文件自己的行号。处理多个文件时区别立刻显现:awk '{print NR, FNR}' file1 file2。如果把两个文件的内容合并对比,这个区别是绕不过去的。还有一个高频区别是NF和NR,NF是当前行的字段数,NR是当前处理的行号。很多新手到这里就晕了。我建议回答时直接举例如echo "a b c" | awk '{print NF, NR}',输出3和1,让面试官知道你理解字段和记录的差异。
4.2 awk高频面试题拆解
awk在面试中最常考的几类题:统计类、去重类、分组类、格式化输出类。
统计文件总行数:awk 'END{print NR}' file。注意理解为什么写在END里。NR在每行处理完都会被更新,END块输出的NR就是最后的行号,也就是总行数。
统计某列数值的总和和平均值:awk '{sum += $2} END{print "sum:", sum, "avg:", sum/NR}' file。为什么用NR做分母?因为每行都是一条记录,NR就是有效记录数。但这里有个细节:如果文件含有表头,直接除以NR会算错,需要先把表头行跳过:awk 'NR>1{sum += $2; count++} END{print sum, sum/count}' file。这个细节我非常喜欢考,它能反映出候选人有没有在生产日志上实操过。
按状态统计连接数:netstat -ant | awk 'NR>2{print $6}' | sort | uniq -c | sort -rn。这其实已经是组合题了。awk提取状态列,sort排序让相同状态相邻,uniq -c做计数,sort -rn按数量降序排列。这类答案在面试中非常加分,因为完全是实战经验。
找出某列中的最大值:awk 'max < $3 {max = $3; line = $0} END{print max, line}' file。这里注意max初始值是0,如果数据全是负数,这个逻辑会出错,初始值应该设为字段第一个值或者用一句话判断NR==1时赋值。追问这些边界条件,是面试官考察候选人对逻辑严谨性的方式。
4.3 awk统计与去重的实战细节
去重是awk面试题的另一大类。最常见的考题是去除文件中重复的行:awk '!seen[$0]++' file。逻辑拆解:seen默认空数组,取反!后为真,执行打印;第二次遇到相同内容时,seen值已经变成1,!1为假,不打印。这就是为什么它能去重。
变体题目:按第一列去重,但保留第一次出现的完整行:awk '!seen[$1]++' file。如果按第二列去重,同理把$1换成$2即可。这道题如果面试官让你解释“++为什么是后置而不是前置”,你得答出:后置++先取值再加1,第一次判定时seen[$1]还是0,!0为真;如果写成++seen[$1],第一次取值就是1,!1为假,反而一次都不输出。这道题是区分“背答案”和“真理解”的金标准。
再有就是分组计数:awk -F: '{group[$7]++} END{for (g in group) print g, group[g]}' /etc/passwd。用冒号做分隔符,统计系统里不同shell类型的用户数。for循环遍历数组是awk面试必考的一部分,很多人会写for (k in arr),但要说明输出顺序是随机的,如果需要排序还要配合管道。这类题目不仅考察awk本身,也考察了组合使用其他命令的意识。
awk还有一个高频细节:分隔符的设置。默认分隔符是空白字符(空格和制表符),处理/etc/passwd时就得用-F:或BEGIN{FS=":"}。如果字段里本身包含空格,还可以配合-F '[ ,]+'这个正则分隔符写法。加OFS能控制输出的分隔符,比如awk -F: '{OFS="-"; print $1, $3}' /etc/passwd输出时会变成root-0。这个考点常和paste、cut组合出现。
5. 三剑客组合实战:日志排查与性能分析
5.1 从日志中快速定位故障
真实生产环境里,三剑客很少单独使用,组合起来才见功力。举个例子,某次线上接口出错率升高,我的第一反应不是去看监控大盘,而是直接登录服务器拉日志:
grep -E '2025-06-18 14:' app.log | grep 'ERROR' | head -200
先把时间窗口缩小到指定时间段,再过滤出ERROR,最后用head控制输出量,避免刷屏。如果还需要进一步定位到某个具体服务,再加一层grep。这种串联命令的思路比单个命令的熟练度重要得多。面试时如果被问到“线上排查故障的流程”,能用三剑客组合把日志分析的步骤讲清楚,是很强的加分项。
再进一步,把错误信息按类型归类统计:
grep 'ERROR' app.log | sed -E 's/.[([A-Z_]+)]./\1/' | sort | uniq -c | sort -rn
这一段先用sed提取中括号里的错误码,再sort和uniq -c统计出哪种错误最多。很多同学会问为什么不能直接用grep提取错误码?因为grep只能过滤行,不能把行内某一部分抽取出来重组输出。这正是sed的用途所在。
5.2 访问量统计的经典组合
另一个典型场景是Web访问日志分析。假设access.log的格式是IP、时间、请求行、状态码、响应时间,要统计访问量最大的前10个IP:
awk '{print $1}' access.log | sort | uniq -c | sort -rn | head -10
要统计状态码为500的请求占比:
grep ' 500 ' access.log | wc -l
要统计每个接口的平均响应时间(假设URL在第7列,响应时间在第10列):
awk '{url[$7] += $10; count[$7]++} END{for (u in url) print url[u]/count[u], u}' access.log | sort -rn | head -20
这个组合题在面试中很常见,因为它把所有知识点串联了起来:按字段取列(awk)、累加求平均(数组与END)、排序(sort)、取前N(head)。我带的实习生做完这道题后,对awk数组的理解明显上了一个台阶。
5.3 组合题的标准答题步骤
遇到这类组合题,我建议按三步走。第一步明确需求:要“过滤”还是“转换”还是“统计”。第二步选工具:grep负责筛选,sed负责编辑替换,awk负责按字段统计。第三步考虑管道之间的数据结构:每个命令的输出字段是什么,下一个命令要用第几列来操作。
比如问到“查找日志中耗时超过1000ms的请求并打印时间和URL”,我会这样拆:先用awk把第10列(耗时)超过1000的行过滤出来,再用awk打印第4列(时间)和第7列(URL)。如果面试官进一步问“按耗时排序”,再加sort。整个过程像搭积木,每一步的输出都要有清晰预期。
还有一道经典面试题:“统计每个IP访问了哪些页面”。awk '{urls[$1] = urls[$1] " " $7} END{for (ip in urls) print ip, urls[ip]}' access.log。这里用字符串拼接而非数组,体现的是awk变量灵活性的理解。这类题没有标准答案,能跑通、逻辑清楚、边界考虑到位,就是好答案。
6. 面试回答技巧与备考建议
6.1 面试官期待听到什么
我在面试环节看候选人,不只看答案对不对,更看他对命令的理解深度。比如问“grep和awk都能查,为什么这里用awk不用grep?”如果候选人能说出“因为awk能对第一个字段做条件判断并做数值运算,grep只能做字符串模式匹配”,这就是理解到位了。再比如问“一条命令怎么从文本中提取IP并按出现次数排序”,有些候选人能几秒给出方案,有些人在那里抠正则细节抠半天,两者差别就体现在实战经验的厚度上。
面试官不会因为你背下了100道题而录用你,他录用的是那个能解决问题的工程师。所以我的建议是:每道题不仅要会写答案,还要思考“这个命令在这个环节里非它不可吗?换成别的行不行?”这样你在面试现场才不怕追问。
6.2 使用这套100道题备考的正确姿势
至于怎么刷题,我的习惯是不要按顺序从头到尾撸一遍,而是按专题突破。第一轮先把grep的正则题刷完,边刷边在本地环境里亲手跑一下。第二轮集中刷sed的定址和替换,重点理解-n、-i、'1~2'这些参数的组合。第三轮专攻awk,把数组、统计、去重这些题型做透,每一题都至少写一个变体。
建议准备一个markdown笔记,把每道题的“错误答案”也记下来。比如sed -i在macOS和Linux下的差异、grep -c只统计行数不统计次数、awk数组输出顺序不保证等等。这些坑就是面试时让你脱颖而出的话料。
6.3 最后一轮练习思路
最后一轮练习,可以尝试把100道题里的经典场景串起来做一个综合练习。比如给你一段nginx日志,让你在5分钟内回答:哪些IP访问量高?哪个接口响应最慢?有多少请求返回了500?能不能用一条脚本自动生成一份统计报告?
我个人的做法是,把这道综合练习做成一个shell脚本,脚本里同时用grep、sed、awk,并把每一步执行结果输出到一个临时目录方便检查。写完后用一份几千行的真实日志做压测,看看执行效率有没有问题。这种练习方式非常接近真实工作场景,练习过后面试基本不会慌。
最后再分享一个小技巧:面试现场写命令时,不要闷头写完就提交。把自己对命令的分析说给面试官听,比如“这里我用sort是为了让uniq -c能正确计数,因为uniq只能合并相邻的相同行”。这种边写边讲的节奏,一方面展示了你清晰的逻辑,另一方面也给面试官提供了引导你的机会。即使中间某个地方写错了,面试官也更愿意帮你纠偏而不是直接判负。