尧图精选

Linux文本处理命令实战:从grep到awk的管道组合技巧

🕒 发布时间:2026/10/1 11:03:44 📁 来源:尧图网络
刚接触 Linux 的时候我处理文本的方式特别笨用 vim 打开日志按十几下 CtrlF 翻页眼睛盯着屏幕找关键词。后来在一个通宵排查线上问题的夜里我用三条命令在几分钟里从几十万行日志里锁定了出问题的服务。从那次之后我才真正意识到Linux/Unix 下的基础文本处理命令不是一个个孤立的小工具而是一套完整的解决问题的方式。这篇文章我不打算列一个大而全的命令手册而是想从几个命令如何配合起来干活的角度把 grep、sed、awk、sort、uniq、cut、tr、diff 这些最常碰到的命令讲透——它们能做什么、为什么这么做、以及我在实际使用中踩过的坑。如果你是刚入门 Linux 的新手或者准备运维方向面试又或者已经写了不少命令但总感觉单个会用、组合就懵这篇应该能帮到你。1. 一切皆文件理解文本处理命令的底层逻辑1.1 配置文件、日志与命令输出为什么说万物都可以被文本处理Linux/Unix 系统里有一个流传很广的设计哲学叫一切皆文件这句话放到文本处理场景里可以再翻译一层几乎所有和系统交互的结果最终都会落成一行一行的文本。你去看 /etc/passwd每个用户一行冒号分隔各个字段去看 /var/log/nginx/access.log每个请求一行空格分隔 IP、时间、请求路径、状态码跑一条 ps aux每个进程一行执行 df -h每个文件系统一行。配置是文本日志是文本命令输出也是文本。这意味着一件事如果你掌握了文本处理命令就等于掌握了读取和操作系统状态最通用的一种接口。反过来很多新手觉得 Linux 命令难记其实是因为他们把这些命令当成特定工具的按钮而没意识到它们是在处理同一类东西——结构化的文本行。明白了这一点再看任何一条文本处理命令思路都会清晰很多它要么是在行里筛内容要么是在列里切字段要么是在把若干行做排序、去重、合并、对比。理解了这套逻辑后面学习新命令的速度会快得超出你的预期。我自己判断一个命令值不值得学标准很简单它能不能让处理文本这件事少敲几次键盘、少犯几次错。grep、sed、awk 之所以是三大金刚就是因为它们覆盖了筛选、修改、统计这三类最高频的需求。剩下的 head、tail、sort、uniq、cut、tr、diff 则是给这套组合拳打辅助的单独看都很简单但放进管道里威力完全不同。1.2 管道与重定向流水线上的三道基本工序讲具体命令之前必须先讲两个连接件否则你永远学不会组合使用。第一个是管道符|。它的作用非常直白把前一条命令的标准输出直接当作后一条命令的标准输入。想象一个工厂流水线第一个工人负责抓取原始零件第二个工人负责筛选合格品第三个工人负责打包装箱——每个工人只干一件事但零件经手多道工序后最终结果变得非常规整。管道就是这套流水线中间的传送带。比如说cat access.log | grep 404 | wc -l这条命令的意思是先把 access.log 的内容读出来交给 grep 过滤出包含 404 的行再交给 wc 统计行数。三条命令各管一段组合后得到404 请求有多少条这个答案。管道符传递的是字节流不是文件所以中间不会产生临时文件这也是它高效的原因。第二个必备概念是重定向。把输出写进文件覆盖原有内容追加到文件末尾2把标准错误单独重定向21则把错误和正常输出合并到同一路。最常见的组合是python3 script.py run.log 21它会把脚本的正常输出和报错信息全部写进 run.log等脚本跑完再慢慢查日志。如果不加21报错会直接打到屏幕上结果你看到的 log 里全是正常输出唯独缺了关键的错误信息排查起来非常别扭。另一个高频场景是把不想要的内容丢进/dev/null比如find / -name *.conf 2/dev/null搜索整个文件系统时没有权限的目录会疯狂输出 Permission denied加上2/dev/null之后错误信息被丢弃屏幕上只保留真正的匹配结果。这个操作我几乎天天用。关键认知文本处理命令的威力不在于某个命令本身多复杂而在于你用管道把多个只做一件事的命令串起来。写命令的时候先想我要从哪拿数据、中间做几步加工、最终输出什么再往里面填具体命令思路会顺很多。2. 先看再筛head、tail、less、grep 的正确用法2.1 面对大文件一上来就 cat是最常见的入门错误我见过太多新手一拿到文件就cat filename然后整个终端哗啦啦输出几百行眼睛直接看花。cat 适合查看小文件、拼接文件或者配合管道给其他命令提供内容但绝对不适合直接读大文件。正确的打开方式要看你想干什么需求正确命令说明看文件前 20 行head -20 filename也常用head -n 20看文件末尾 30 行tail -30 filename日志最新内容在末尾实时跟踪日志追加tail -f filenameCtrlC 退出分页浏览并可搜索less filename空格翻页、/ 搜索、q 退出带行号看文件cat -n filename小文件排查时好用其中tail -f是我排查线上问题时的救命稻草。服务在跑日志在刷你想看它最新打印了什么用tail -f /var/log/app.log挂在那里新内容会实时滚出来。配合另一个终端窗口做操作基本能实时看到你的改动产生了什么影响。less 是 more 的加强版很多人只知道 less 可以翻页其实它的搜索能力很关键输入/error按回车它会高亮并跳转到下一个 error 的位置按n继续向下找。面对一个几十 MB 的日志先在 less 里搜关键字定位再决定下一步用什么命令做精确筛选比一上来就 grep 整个文件更省力因为 less 不会一次性把整个文件读入内存。还有两个容易被忽略的小命令wc -l统计文件总行数看文件规模心里有底file先确认文件类型有些文件看着像文本实际是带 UTF-16 编码或者压缩过的直接用 grep/text 处理会得到一堆乱码。2.2 grep 筛选与正则从找一行到精确命中grep 是文本处理里出场率最高的命令它的核心逻辑是逐行读取输入把匹配到的行打印出来。最简单的用法是在文件里找关键字grep ERROR app.log但实际工作中没人这么将就因为日志里的 ERROR 千奇百怪你需要控制匹配的精度和范围。下面这些选项我建议直接记熟选项作用示例-i忽略大小写grep -i error app.log-v反向匹配输出不包含关键字的行grep -v ^# nginx.conf-n显示匹配行在文件中的行号grep -n timeout config.php-c统计匹配行数不输出具体内容grep -c 404 access.log-r递归搜索目录下的所有文件grep -r server_name /etc/nginx/-l只列出包含匹配内容的文件名grep -l root /etc/*.conf-E使用扩展正则表达式grep -E ERROR|FATAL app.log-o只输出匹配到的部分而不是整行grep -o 1\.[0-9]\\.[0-9]\ file这里特别想强调-v和-E的价值。看配置文件时最常见的一类操作是排除空行和注释行grep -v ^# /etc/nginx/nginx.conf | grep -v ^$第一条把以 # 开头的注释行去掉第二条把空行去掉剩下的就是真正生效的配置内容排查配置问题效率直接翻倍。-E则是进入正则世界的门票。基础正则和扩展正则的区别是很多人的知识盲区简单说基础正则里、?、{、|需要加反斜杠才有效果扩展正则里直接写就行。所以为了少挨两下反斜杠的毒打我一般直接上grep -E。举一个真实场景统计日志里出现 ERROR 或 FATAL 的条目数量。grep -E ERROR|FATAL app.log | wc -l再进一步如果你想知道这些错误都分布在哪些行方便去定位代码位置grep -nE ERROR|FATAL app.log | head -20正则里几个符号必须掌握^匹配行首$匹配行尾.匹配任意单个字符*表示前一个字符出现任意次包括零次[]表示字符集合[^]表示取反。例如匹配一个典型的 IP 地址grep -E ^[0-9]\.[0-9]\.[0-9]\.[0-9] access.log这段会筛出所有以 IP 开头的行也就是大部分 Web 访问日志的标准开头。刚起步时不用背太复杂的正则先把行首、行尾、字符集、通配这四个概念吃透能解决九成问题。还有个大坑必须提醒很多人喜欢ps aux | grep nginx结果输出里经常混着一条grep nginx自己的进程。这不是 bug而是因为 grep 匹配的是整行文本它自己的命令行里也包含 nginx 这个字符串。解决办法是加一层排除ps aux | grep nginx | grep -v grep或者用更优雅的写法ps aux | grep [n]ginx把 nginx 的第一个字母放进字符集grep 自己的命令行里匹配的是[n]ginx字面文本就不会中招了。这个技巧面试的时候说出来能加分不少。3. sed 与 awk流式修改和按列计算的黄金搭档3.1 sed 的替换、定位与原地修改以及如何安全使用 -ised 的全称是 stream editor翻译过来是流式编辑器。它和 vim 这类交互式编辑器最大的区别是sed 处理文本时不打开文件而是像流水线一样一行一行读入、处理、输出。这种方式在处理大文件、批量修改时优势巨大因为你不需要加载整个文件到内存。sed 最常见的操作是替换基本语法是sed s/旧内容/新内容/标志。比如所有把 localhost 改成 127.0.0.1sed s/localhost/127.0.0.1/g app.conf注意最后的g它代表全局替换每一行中所有匹配位置。如果不加 gsed 只替换每一行第一个匹配到的位置。下面这个例子最能说明问题echo test test test | sed s/test/foo/ # foo test test echo test test test | sed s/test/foo/g # foo foo foo实际改配置时老板突然说把 8080 端口全改成 9090你不会去开编辑器一行行调。直接sed -i s/8080/9090/g nginx.conf-i是原地修改in-place它会直接改写文件内容。但我强烈建议每次用 -i 都加后缀做备份sed -i.bak s/8080/9090/g nginx.conf执行后会生成一个 nginx.conf.bak 备份文件万一改错了一条mv nginx.conf.bak nginx.conf就能还原。这个习惯帮我避免过好几次灾难性错误尤其是同时改多个文件的时候。sed 除了替换还能做定位删除和打印。删除文件第 3 到第 5 行sed 3,5d notes.txt只看第 1 到第 10 行sed -n 1,10p notes.txt这里的-n和p是一对组合-n 表示默认不输出任何行p 表示打印指定的行。没有 -n 的话sed 会把全部内容都打印一遍再额外打印你指定的行输出会非常乱。sed 里按正则定位也很常用。比如你想删掉所有以#开头的注释行sed /^#/d config.txt或者只想替换某一段范围内的内容比如从 BEGIN 行开始到 END 行结束之间的所有 foo 换成 barsed /BEGIN/,/END/s/foo/bar/g file.txt这种区间操作的写法在脚本里处理配置文件片段时非常好用。3.2 awk 的字段、NR/NF 与统计能力如果说 sed 是按行处理那 awk 就是按行加按列同时处理而且自带计算能力。awk 的默认逻辑是把输入按空白字符分成多个字段$1 是第一个字段$2 是第二个$0 是整个一行。举个例子awk {print $1, $3} access.log这会打印每行的第一个字段和第三个字段比如来源 IP 和请求状态码。字段分隔符可以自定义处理 /etc/passwd 时每行以冒号分隔awk -F: {print $1} /etc/passwd这条命令把 /etc/passwd 里所有用户名列出来因为用户名是冒号分隔后的第一个字段。-F:就是用冒号当分隔符的意思。awk 里有两个内建变量必须理解NR当前已经处理的行数Number of RecordNF当前行的字段数量Number of Field举个例子当你看到awk {print NF} file它输出的就是每行有多少个字段。而awk NR5 {print $0} file是精确打印第 5 行。面试官很喜欢问 NR 和 NF 的区别这两个字母背后其实是 awk 处理模型的两大核心概念记录和字段。再往下awk 真正的进阶点是 BEGIN 和 END。BEGIN 块在处理任何行之前执行适合初始化变量END 块在所有行处理完之后执行适合输出统计结果。最经典的例子是求和awk {sum $1} END {print sum} numbers.txt如果 numbers.txt 里每行一个数字这条命令会把所有数字加起来。你可能会说那我自己心算不就行了但当文件里有几万个数字时这行命令的价值就体现出来了。另一个极其实用的场景是统计 access.log 里每个 IP 的访问次数awk {count[$1]} END {for (ip in count) print ip, count[ip]} access.log这里count[$1]是在用一个数组记录每个 IP 出现的次数END 循环打印结果。再搭配 sort 排序就能得到访问量最多的 IP 排行榜。这个组合拳我后面在实战章节会再展开。awk 还支持条件过滤。比如过滤出状态码大于等于 500 的行awk $9 500 {print $0} access.log这里 $9 是日志里的状态码字段具体列号取决于日志格式awk 会自动把字段内容当数字比较。很多新手觉得 awk 语法像天书我的建议是别一上来啃完整语法先记住三个模板取列awk {print $X}过滤awk 条件 {动作}统计awk {计数逻辑} END {输出}这三个模板覆盖了日常 80% 的需求其余细节用到再查。3.3 cut、tr、paste字段级处理的轻量备选awk 很强但有些简单的切分工作不必动用它。cut 就是干这个的cut -d: -f1 /etc/passwd效果和前面的awk -F: {print $1} /etc/passwd一样都是提取冒号分隔后的第一个字段。区别是 cut 更轻量如果你的需求只是取某一列用 cut 就够了不需要学 awk 的语法。cut 还有两个独门用法-c按字符位置切割-b按字节切割。比如提取每一行的第 2 到第 5 个字符cut -c2-5 file.txt这个在快速查看固定格式字段时很管用。tr 是字符级别的转换器它不处理行或字段而是处理字符常用于清理数据。把文件里的所有小写字母变成大写tr a-z A-Z notes.txt删除文件里的回车符处理 Windows 换行的 CRLF 时巨好用tr -d \r windows.txt unix.txt这里有个细节tr 后面的\r是回车符配合重定向把处理结果写到新文件。把连续多个空格压缩成一个空格tr -s file.txt-s是 squeeze压缩连续重复字符。这类清洗工作用 tr 一行搞定比写 Python 脚本快得多。paste 则是把多个文件按行并排拼接用制表符分隔。把两个文件的内容合并成一列一列的表格paste name.txt phone.txt contacts.tsv虽然日常用得不算多但在处理从不同日志源导出的同类数据时paste 能快速完成横向合并。记住 cut、tr、paste 三个命令的定位轻量、单一、适合在管道里做前置或后置清洗。4. sort、uniq、diff排序、去重与差异对比4.1 sort 的数值排序、指定列排序与 locale 陷阱sort 的名字叫排序但很多人对它的理解停留在按字母排一排实际上 sort 有大量精细化控制选项。默认情况下sort 按字典序排序。这带来一个经典问题如果你对一个全是数字的文件直接 sort得到的结果会让你抓狂# 文件内容10 9 100 2 1 sort numbers.txt # 输出1 10 100 2 9为什么 10 排在 2 前面因为字典序比较的是字符1 比 2 小所以 10 和 100 都排在 2 前面。要按数值大小排必须加-nsort -n numbers.txt # 输出1 2 9 10 100-n是 sort 最常用的选项没有之一。很多人在统计脚本里拿到的排序结果不对劲十有八九就是这里出了问题。-r反转排序得到降序sort -rn numbers.txt-k指定按第几列排序-t指定分隔符。比如按 access.log 里的响应时间字段排序sort -t -k10 -n access.log这里假设第 10 列是响应时间具体列号看日志格式-k10 -n表示按第 10 列数值排序。还有一个很隐蔽的坑locale 会影响 sort 对大小写和特殊字符的处理。在中文 locale 环境下某些字符的排序结果可能和预期不同。如果你写脚本时发现 sort 结果莫名不对可以加上LC_ALLC强制用 C 语言环境的传统排序规则LC_ALLC sort file.txt这个细节我在脚本交付时踩过一次当时同事的英文系统和我中文系统的 sort 结果不一致排查了半天才定位到是 locale 差异。4.2 uniq 为什么必须先 sort 才能去重uniq 命令的意思是去除重复行但它有一个很反直觉的设定它只去掉相邻的重复行。什么意思假设文件内容如下apple banana apple直接uniq file.txt输出仍然是三行因为两个 apple 中间隔了一个 banana它们不相邻uniq 认为它们不是重复的。只有先排序让相同的行聚到一起uniq 才能发挥作用sort file.txt | uniq输出就变成了 apple、banana 两行。或者更准确地说是apple、banana 各一个。所以江湖上流传的组合命令是cat file.txt | sort | uniq先把所有行排序相同项聚拢再交给 uniq 去重。这个流程用到极其频繁。uniq 最实用的选项是-c统计每行出现次数sort access.log | uniq -c | sort -rn这条命令把 access.log 按内容排序后统计每行重复次数并按次数降序排序。看起来平平无奇但它其实是很多日志分析场景的万能骨架——把文件内容换成 IP、状态码、用户 ID你就得到了访问量排行、状态码分布、用户活跃排行。-d只输出重复行-u只输出不重复行在数据清洗时能直接找出异常重复记录。提醒uniq 的兄弟命令有一个特殊行为就是它会把空行也当成有效内容参与去重和计数处理日志时如果混入了大量空行统计结果会非常难看。建议在 sort 之前先用 grep -v ^$ 把空行过滤掉或者用tr -s \n压缩连续换行。4.3 diff 与 patch配一本对照账本diff 用于逐行比较两个文件输出它们的差异。最基本的用法diff old.conf new.conf它输出的格式对新手来说有点抽象所以我更推荐-u选项展开成上下文格式diff -u old.conf new.conf输出里-开头的是旧文件独有的行开头的是新文件新增的行其余是共同内容。配合 -1,5 1,6 这样的区间标记一眼就能看出修改集中在文件的哪个位置。diff 最常见的用途是改配置前先留底改完对比自己动了哪些地方。比如你接手一台服务器不知道前人改过什么先备份当前配置改完跑一条diff -u /etc/nginx/nginx.conf.bak /etc/nginx/nginx.conf所有改动瞬间一目了然比翻历史记录或者靠记忆靠谱得多。patch 命令则用于把 diff 生成的差异应用到另一个文件上。如果 diff 输出保存成了 patch 文件diff -u old.conf new.conf change.patch patch old.conf change.patchold.conf 就被改成了 new.conf 的内容。这套机制在代码审查、批量同步配置、给开源项目打补丁时仍然大量使用。我在多个环境同步 nginx 配置时就靠 diff patch 批量推送比直接覆盖文件安全因为先生成补丁、检查补丁、再应用补丁每一环都能验证。5. 三场实战日志分析、批量改配置、系统状态提取5.1 access.log 里的访问量、404 与来源 IP理论说多了容易飘来点实际能直接抄走的组合命令。场景一分析 Nginx 访问日志找出访问量最大的 10 个 IP。awk {print $1} /var/log/nginx/access.log | sort | uniq -c | sort -rn | head -10这条命令拆开看很有代表性awk 提取 IP 列sort 让相同 IP 聚拢uniq -c 统计次数sort -rn 按次数降序head -10 取前 10 名。四个命令各管一步全程没有生成临时文件几十万行的日志也在几秒内出结果。场景二统计状态码分布看看整体健康度。awk {print $9} /var/log/nginx/access.log | sort | uniq -c日志格式里第 9 列通常是对应状态码这条命令能告诉你 200、301、404、500 分别有多少。如果 500 的数量异常就该去翻后端服务日志了。场景三找出所有 404 的请求路径排查是否有异常扫描。awk $9 404 {print $7} /var/log/nginx/access.log | sort | uniq -c | sort -rn | head -20$7 一般是对应的请求 URI。同样一套 sort | uniq -c | sort -rn 骨架换一列就是换一种分析维度。搞清楚这个思路以后你会发现日志分析根本不玄学本质就是提取目标列 排序计数 取前几名。如果想看最近 5 分钟的请求量可以用 tail 限制范围tail -5000 /var/log/nginx/access.log | wc -l虽然这是按行数近似时间窗口但日常快速判断流量是不是突增已经够用了。真要精确按时间过滤可以结合 grep 的正则匹配时间字段。5.2 批量修改多个配置文件如何用一条命令完成静态单文件替换很简单实际工作中更常见的是你要在一个项目目录下把所有配置文件里的旧域名全换成新域名。这时候 find 和 sed 要联动find /home/user/project -name *.conf -exec sed -i s/old.example.com/new.example.com/g {} \;find 找到所有 .conf 文件-exec对每个文件执行后面的 sed 命令{}是当前找到的文件名的占位符\;表示命令结束。一行命令直接改完整个项目。但正因如此这行命令非常危险改错一次就是几十个文件集体中招。所以我实际操作时会分成三步走第一步只打印将要被修改的文件列表find /home/user/project -name *.conf | head -20第二步先做替换预览不实际写文件sed s/old.example.com/new.example.com/g sample.conf确认替换结果无误之后第三步才真正执行带-i的批量修改并且每份文件都要留备份find /home/user/project -name *.conf -exec sed -i.bak s/old.example.com/new.example.com/g {} \;全部改完后用 grep 验证是否还有遗漏grep -r old.example.com /home/user/project/ || echo 替换完成无残留||表示前一条命令失败才执行后面的grep 找不到匹配时返回非零状态码此时输出替换完成提示。这套先预览、再备份、后执行、最后验证的习惯能避免 99% 的批量修改事故。5.3 从 ps、df 里提取数据做一条告警命令系统状态命令的输出也是文本同样能用文本处理命令加工。比如查看当前系统里 CPU 消耗最高的 5 个进程ps aux | sort -k3 -rn | head -5ps aux 输出的第三列是 CPU 使用率sort -k3 -rn 按第三列降序排列head -5 取前 5 条。这条命令比单独看 ps 输出直观太多一眼就能知道是谁在吃 CPU。查看根分区磁盘使用率并判断是否超过 80%df -h / | awk NR2 {print $5}df 输出的第二行是根分区信息第五列是使用率。如果想去掉百分号做数值判断df -h / | awk NR2 {gsub(%, , $5); if ($5 0 80) print 磁盘告警, $5%}gsub是 awk 里的字符串替换函数把 % 去掉后转为数值比较。这种命令写进监控脚本里比装一堆监控 Agent 要轻量得多。再比如批量杀掉某个服务的进程把 ps 和 awk 提取 PID 的能力用起来kill $(ps aux | grep my-service | grep -v grep | awk {print $2})中间那层grep -v grep是为了过滤掉 grep 自身。$() 命令替换会先把括号里的命令执行完再把输出作为 kill 的参数。这里有风险如果没匹配到任何进程kill 会收到空参数报错所以更稳妥的写法是先保存 PID 列表再检查PIDS$(ps aux | grep my-service | grep -v grep | awk {print $2}) [ -n $PIDS ] kill $PIDS || echo 没有找到相关进程[ -n $PIDS ]判断变量非空非空才执行 kill。写脚本时宁可多写两行判断也不要留一个可能误操作的空命令。6. 踩过的坑与面试考点文本命令的真正门槛6.1 引号、别名、编码三个让我半夜翻车的样本第一个坑是引号。单引号、双引号、反引号新手经常混。核心区别是双引号里的变量和通配符会被展开单引号里的内容原封不动。举个例子echo $HOME # 输出 $HOME echo $HOME # 输出 /root或其他用户主目录在 grep、sed 的正则表达式里这个差异会直接导致匹配失败。比如你想匹配一个包含$符号的文本如果用双引号包正则$会被 shell 当成变量符号处理结果完全不对。所以处理正则表达式时我习惯一律用单引号省得考虑 shell 展开问题。反引号则是命令替换等价于$()但嵌套时容易出错现在我都用$()代替。第二个坑是别名alias。很多 Linux 发行版默认把 grep 设置成了grep --colorauto这本身挺方便但如果你在脚本里用了 grep 且依赖它的输出做判断有时会因为高亮控制字符混入输出而踩坑。更隐蔽的是某些系统把 ls、rm 都设置了别名你在脚本里写的ls实际执行的可能不是 /bin/ls。排查这种问题的方法是用type -a grep查看命令实际指向或者写脚本时直接用绝对路径。第三个坑是文件编码和不可见字符。处理 Windows 传过来的文本文件时行尾会带\r回车符导致 grep 匹配明明看着一样的字符串却失败、awk 最后一列总是多出个看不见的字符。解决方案是先清洗sed -i s/\r$// windows.txt或者用tr -d \r。另外如果文件包含中文字符grep 匹配时还要关注当前 localegrep -P的 Perl 正则在某些环境下能解决 UTF-8 匹配问题但这个选项在不同平台兼容性一般慎用。还有一类很坑的是全角空格或特殊空白字符肉眼看不出来正则里的[[:space:]]或[[:blank:]]能更稳妥地匹配各种空白这时候别用普通的空格字符直接做分隔符。6.2 面试常考的文本处理题到底在考什么面试题里有一类出现频率奇高就是统计日志里某个字段的 Top 10考的是你能否把 awk、sort、uniq、head 串起来。比如有一个 access.log每行格式是IP 时间 请求 状态码如何统计出现次数最多的 IP Top 5参考答案是awk {print $1} access.log | sort | uniq -c | sort -kn1 | tail -5这里有个小差异如果用 head 加 sort -rn 取前 5可以写成sort -rn | head -5如果面试官要求答案用 tail那就是先按升序排再取最后的 5 行等价但写法不同。重点是表达出先提取字段、再排序、再去重计数、再排序取前几名这个思路。另一个高频考点是如何把文件里的某个字符串批量替换。考的是 sed -i 的安全使用sed -i.bak s/foo/bar/g *.conf面试官大概率会追问-i后面跟 .bak 是什么意思以及不加 g 会怎样。能答出备份、全局替换、防止误改就算合格。还有一类题是查找并删除 7 天前的日志文件考 find 和 xargs 的配合find /var/log -name *.log -mtime 7 -exec rm {} \;或者用管道版本find /var/log -name *.log -mtime 7 | xargs rm这里特别提醒文件名带空格时xargs会拆错加-print0和xargs -0才稳妥find /var/log -name *.log -mtime 7 -print0 | xargs -0 rm这两个零后缀约定成俗的原因就是应对文件名里的特殊字符。面试时如果能主动说出这个细节面试官会觉得你是个踩过坑的人而不是背语法的人。最后还有一类低频但冷门的问题awk 的 NR 和 NF 有什么区别我在前面章节已经讲了NR 是已处理的行数NF 是当前行的字段数。再有就是wc -l 统计的是换行符数量如果文件最后一行没有换行符wc -l 的结果会少一行这个细节在一些精确校验场景会坑你一次。写在最后的一点个人经验如果让我给刚接触 Linux 的新手一个优先级排序我的建议是先死磕 grep、awk、sed 三个再补 sort、uniq、cut、tr最后把 diff 和 patch 用熟。顺序别反因为前三者是加工主力后面的是辅助管线主次分明才能快速上手。我在实际操作中的体会是文本处理命令真正难的不是记语法而是在具体场景里知道该选哪条命令、该和哪条命令组合。这种手感只能靠实际处理日志、批量改配置、写脚本时慢慢积累。建议你从今天开始遇到任何需要打开文件看内容的需求先停下来问自己一句能不能用一条命令完成能不能不打开编辑器这个习惯坚持一个月你处理文本的方式会发生质变。最后分享一个小技巧把你自己最常用的组合命令写成 shell 别名放到 ~/.bashrc 里比如alias topipawk {print \$1} access.log | sort | uniq -c | sort -rn | head -10 alias cleancfggrep -v ^# | grep -v ^$下次直接敲别名就能复用整套流程这才是把文本处理命令变成自己工具的真正开始。
上一篇/下一篇内容由系统自动关联 返回资讯列表 →