资讯动态

Linux文件内容查看与处理:grep、sed、awk高效实战

发布时间:2026/9/18 10:14:51 来源:尧图企业网站定制
用Linux查文件、改内容最忌只会cat然后一通翻。很多人拿到一个几千行的日志或者一份配置第一反应就是cat屏幕上刷过去几百行眼睛看花还得再开一个终端重新查。这篇文章是Linux常用命令汇总系列的第三篇聚焦两件事一是把文件内容怎么看清楚、怎么定位到关键位置二是拿到内容之后怎么处理——筛选、替换、排序、去重、统计、对比。覆盖的命令包括cat、less、tail、grep、sed、awk、sort、uniq、diff以及它们配合管道组合出来的各种实战姿势。适合谁看刚入行的运维、天天和服务器日志打交道的开发、准备Linux面试的测试都值得花十分钟过一遍。这里面的每一条命令我都压过真实场景不是背课本是干活用的。1. 文件第一眼cat、nl、head、tail怎么选1.1 cat不只是输出搭配参数能看出隐藏字符cat全称是concatenate本来就是连接文件用的cat file只是它最简单的用法。很多人不知道两个实用参数-n显示行号-A把行尾、制表符、不可见字符全部显形。# 显示行号 cat -n /etc/hosts # 查看隐藏字符$表示行尾^I表示Tab cat -A /etc/resolv.conf用cat -A能解决一个很经典的怪问题在Windows上编辑过的脚本拿到Linux里执行报错$\r: command not found。原因就是Windows换行符是\r\nLinux只认\n多出来的\r被当成命令的一部分。cat -A看到行尾多个^M$基本就能确诊。处理办法是sed -i s/\r$// script.sh后面讲sed时会细说。小文件用cat没问题但文件一旦超过一屏就不建议了。信息量太大输出根本看不过来还污染终端这时候需要的是下面这几个命令。1.2 head和tail取头、取尾、动态跟踪head取文件开头默认前10行-n指定行数。tail取文件结尾同样默认10行。这两个命令看着简单实战里组合起来非常有用# 看配置文件前50行 head -n 50 /etc/nginx/nginx.conf # 看日志最后200行排查问题时最常用的起手式 tail -n 200 /var/log/messages # 取第101到200行先取头200行再取这个结果的尾100行 head -n 200 app.log | tail -n 100第三个写法值得说一句它演示的是管道思维把前一个命令的输出传给后一个继续处理。这个思维贯穿整个内容处理主题后面全是这套逻辑。head和tail都能接多个文件输出会带上文件名分隔标记批量查看时很好认。1.3 nl和wc带行号查看顺便数一数有多少行nl就是cat -n的专门版但比cat -n灵活。它能设置行号格式nl -ba表示所有行都编号包括空行nl -v 100表示从100开始编号。大文件里想精确引用某一行比如第45行报错了nl的输出格式比cat -n更适合直接发给同事看。wc是word count但最常用的是两个参数# 统计行数 wc -l access.log # 统计字节数、字符数 wc -c file.txt wc -m file.txt看配置文件、查日志总量时wc -l几乎是本能操作。还有一个很实用的场景配合grep统计匹配次数比如ps aux | wc -l能数出当前有多少条进程记录。要注意wc -l数的是换行符个数如果文件最后一行没有换行符统计结果会比实际行数少1这个细节在看程序生成的文件时偶尔会踩到。2. 大文件和实时日志less与tail -f是运维的命根子2.1 less的翻页哲学不读完整个文件也能定位Linux文件查看器那么多less是我用得最顺手的原因在于它操作逻辑更像编辑器而不是cat。打开不着急翻第一件事是搜索关键词定位。less /var/log/syslog # 进入less之后的操作 # 搜索往后找按n跳到下一个匹配 /ERROR # 搜索往前找 ?timeout # 跳到文件末尾 G # 跳到文件开头 gg # 按行号跳转先输数字再按G 150G # 带上行号显示 less -N file.txtless不会一次性把大文件读进内存所以打开几个GB的日志也不卡。它的-S参数也很有用默认超长行会折行显示less -S改成不折行左右方向键能水平滚动。查看某些程序导出的超长单行数据时-S比折行舒服得多。less里还有一个经常被忽略的功能按v直接进入默认编辑器编辑当前文件改完退出又回less。排查配置时发现错误顺手就改了不用另开一个终端。2.2 tail -f与tail -F的区别关键时刻能救命tail -f用于实时跟踪文件新增内容是盯日志的标配tail -f /var/log/nginx/access.log # 如果文件被轮转logrotate把access.log重命名成access.log.1新建了access.log-f会跟丢 # 正确做法用大写-F它会按文件名重新打开文件 tail -F /var/log/nginx/access.log这个区别很关键。日志轮转在Linux里是常见的定时任务老日志被改名新日志在原文件名下写入。-f跟踪的是打开的文件一旦轮转发生它继续读的是.1那个旧文件-F则每次都检查文件名会自动切过去。排查Nginx、系统日志这些问题时务必用-F。如果日志输出太快刷屏可以加-n 50让tail先显示最后50行再进入跟踪模式这样上下文有一段铺垫不至于一进去就是空屏。2.3 实战安装程序报警告错误时怎么快速查.err和.log安装软件或运行部署脚本时经常看到提示安装完成但出现警告错误请查看任何.err或.log文件。这个提示其实是让你去翻日志定位问题不是让你干瞪眼。我处理这种场景的固定套路是# 第一步先看当前目录下有哪些日志文件按时间倒序 ls -lt *.log *.err 2/dev/null || find . -name *.log -o -name *.err # 第二步把最大的或者最新的日志尾部打开看 tail -n 100 setup.log # 第三步grep过滤出错误级别的内容 grep -iE error|warn|fail setup.log第三步里的-i忽略大小写-E启用扩展正则error|warn|fail是三个关键词的或关系。这个组合实际使用频率极高比一条条grep分开查省事。对于那种几百MB的日志grep完仍然很长再加tail -n 20只取最后20行往往是错误堆栈的根因所在。3. 内容检索grep的进阶玩法与匹配哲学3.1 基础参数速记不想记那么多就死磕这几个grep是Linux里使用频率最高的命令之一参数非常多但日常维护我实际用到的就这几个参数作用典型场景-E扩展正则支持、、?-i忽略大小写查日志时大小写混乱-v反向匹配排除过滤掉干扰行-r递归搜索目录在项目代码里找函数-l只输出文件名想知道哪些文件有匹配-n显示行号定位到具体行-c统计匹配行数数一下出现了多少次-A/-B/-C显示匹配行之后/之前/前后N行查看上下文-A、-B、-C这几个参数查日志时特别有价值。错误不会孤立出现它的前几行往往是触发的操作后几行是堆栈和结论。只grep ERROR只能看到孤立行配合-B 5 -A 10就能把完整现场复现出来。3.2 多文件搜索与排除在目录里快速定位关键词grep不仅能搜单个文件还能递归搜目录这是查代码、查配置最快的方式# 在当前目录所有文件里递归搜索timeout grep -rn timeout . # 只搜索指定类型的文件 grep -rn --include*.conf timeout /etc/nginx/ # 排除掉二进制和日志文件专注源码 grep -rn --include*.py --exclude*.log def handle ./src # 只列出包含关键词的文件名 grep -rl 404 /var/www/html/error_logs/这里有个性能建议如果目录特别大先find定位再grep比grep -r直接扫全目录要快。比如搜索一个大型前端项目的node_modules不加--exclude-dirnode_modules会等到怀疑人生。3.3 grep与正则结合提取IP、版本号、时间戳grep支持基础正则和扩展正则最常见的用法是从混乱输出中揪出结构化信息。比如从日志里提取所有IPv4地址grep -oE ([0-9]{1,3}\.){3}[0-9]{1,3} access.log | sort | uniq -c | sort -rn-o参数表示只输出匹配到的部分不会把整行都打出来。这个参数在提取场景里是核心配合-E的正则可以从任何文本里抽IP、抽邮箱、抽时间戳。上面的命令把sort、uniq -c、sort -rn串起来了后面第6节会详细拆解这三个命令的组合逻辑。grep的正则有一些需要注意的习惯基础正则应使用grep pattern扩展正则使用grep -E。、?、|、()这些字符在基础正则里是普通字符必须转义才能生效所以建议直接统一用-E少踩坑。4. 用sed做非交互式编辑批量替换、行删除与原地修改4.1 替换语法与分隔符陷阱sed在没有交互环境下改文件非常高效最核心的功能是替换# 把文件中的localhost替换成127.0.0.1并输出到屏幕 sed s/localhost/127.0.0.1/g hosts.txt # 将结果写回原文件注意macOS和Linux语法有区别 sed -i s/localhost/127.0.0.1/g hosts.txts是替换命令g是全局替换标志没有g的话每行只替换第一个匹配项。这个细节看需求决定如果是替换每行的第一个出现的日期不加g如果是替换所有同名变量加g。分隔符不一定是/。替换路径时路径本身就带斜杠再用/做分隔符就得疯狂转义比如sed s/\/usr\/local/\/opt/g看着就头疼。解决办法是换个分隔符sed支持任意字符做定界符# 用#做分隔符替换路径无需转义 sed s#/usr/local#/opt#g config.txt4.2 按行号删除、打印指定范围sed另一个高频用途是按行号操作# 删除第3行在原文件上操作 sed -i 3d file.txt # 删除第5到10行 sed -i 5,10d file.txt # 只打印第20到30行-n表示静默模式不输出未匹配行 sed -n 20,30p file.txt # 删除空行 sed -i /^$/d file.txtsed -n 20,30p这个用法在查看大文件里某一区间时很好用等价于head -n 30 file.txt | tail -n 11但写法更优雅。我还经常用sed -n $p打印最后一行文件不大时比打开整个文件快。4.3 原地修改的备份习惯和中文乱码处理sed -i在Linux和macOS上有差异Linux直接生效macOS要求sed -i 后面跟空字符串参数如果不加会报错。更稳的做法是养成备份习惯# 修改前备份成file.txt.bak sed -i.bak s/old/new/g file.txt这个习惯意义重大尤其在生产环境改配置文件。万一替换规则写错把不该替换的内容全改了还能从.bak恢复回来。我见过同事把配置文件里所有1替换成2结果版本号、端口号全军覆没没有备份只能从源码重新生成配置。处理中文乱码还有个连带场景从Windows拷贝过来的文件经常是GBK编码Linux下显示成乱码。这种情况先不要用sed硬替先转码# 查看文件编码 file -i file.txt # GBK转UTF-8 iconv -f GBK -t UTF-8 file.txt file_utf8.txt转码后再做替换或者先转码再操作就不会出现拿乱码当内容去匹配的尴尬局面。file -i这个命令本身也属于查看文件主题它能判断文件类型和编码排查问题第一步就该用。4.4 在管道里做实时替换输出sed不只是文件修改工具它还能在管道里对输出流做实时编辑不改动原文件# 直接看日志但把INFO级别去掉避免刷屏 tail -F app.log | sed /INFO/d # 把输出的IP替换成内网域名方便调试 cat access.log | sed s/192\.168\.1\.[0-9]*/internal/g这个场景很常见程序日志输出量太大直接tail根本看不过来用sed过滤掉不关心的级别只留WARN和ERROR。注意sed是逐行处理管道模式下实时性没有问题日志一行行进来就一行行处理。5. awk字段处理按列拆、按条件过滤、求和统计5.1 指定分隔符精准取列awk处理的是字段概念默认以空格或Tab做分隔符。$1是第一列$2是第二列$NF是最后一列$0是整行。按列提取是awk最基础的用法# 打印每行的第一列和第三列 awk {print $1, $3} access.log # 以冒号为分隔符提取/etc/passwd的用户名和家目录 awk -F: {print $1, $6} /etc/passwd-F指定分隔符这个参数几乎每次用awk都会带。查看/etc/passwd、处理/proc下的状态文件、解析启动参数这些场景的格式都是特定分隔符-F是标配。5.2 内建变量的实用场景NF、NR、OFSawk有几个内建变量非常常用NR当前行号从1开始NF当前行的字段数量OFS输出字段分隔符默认是空格# 输出行号与内容 awk {print NR: $0} config.ini # 打印每行最后一个字段 awk {print $NF} file.txt # 自定义输出分隔符为逗号 awk -F: BEGIN{OFS,} {print $1, $3} /etc/passwdNR配合条件表达式可以做只处理指定行区间的逻辑比如awk NR10 NR20 file.txt只输出第10到20行。NF判断字段个数在数据清洗时很实用行格式不一致的脏数据可以快速过滤掉。5.3 实战示例提取内存和PID、统计URL访问量awk的统计能力是它区别于其他命令的最大亮点。下面的例子可以从进程列表里按内存排序# 按物理内存排序输出PID和RSS单位KB-k表示按第6列排序-n按数值 ps aux | awk {print $2, $6, $11} | sort -k2 -n | tail -n 5但awk更强的地方是直接做聚合统计。统计访问量Top N的URL# 提取第7列URL统计出现次数按次数倒序取前10 awk {print $7} /var/log/nginx/access.log | sort | uniq -c | sort -rn | head -n 10这正是第6节会重点展开的组合管线。awk把每一行的某个字段抽出来后续命令接着处理这种分工协作模式在处理日志时效率极高。5.4 awk与grep、sed的分工边界这三个命令是内容处理三剑客很多人分不清什么时候用谁。我的理解很简单grep负责挑行——看这一行要不要sed负责改内容——对文本做替换、删除awk负责拆列——把一行拆成多个字段去操作。它们可以互相组合比如先grep过滤出Error行再用awk提取时间戳最后sed改写格式grep ERROR app.log | awk {print $1, $2, $5} | sed s/T/ /这条命令的意思是先挑出包含ERROR的行再把行按空格拆开只取第1、2、5列最后把时间戳里的T替换成空格。一个复杂需求用三个命令拆解各自的边界清晰出错也好排查。6. 排序、去重与差异比较sort、uniq、diff、cmp各管一摊6.1 sort排序参数数值、列、倒序一个不能少sort看着简单坑不少。默认按字典序排序所以10会排在9前面这在处理数字时必须注意# 按数值排序按第一列数值大小 sort -n file.txt # 按第二列数值倒序 sort -k2 -n -r file.txt # 以冒号分割按第三列排序 sort -t: -k3 -n /etc/passwd # 去重排序sort -u等价于sort | uniq sort -u file.txt-k指定列-t指定分隔符-r倒序。这三个参数组合起来能处理绝大多数排序需求。比如查看磁盘空间时df -h的输出想按使用率排序用sort -k5 -n按第五列使用率排但要注意-h参数sort本身也支持-h自动识别K/M/G单位处理df -h这种带单位的输出用sort -k5 -h才是正解。6.2 uniq去重与统计必须搭配sort才有效uniq只能去除连续且重复的行如果文件里相同的行不挨在一起uniq是去不掉的。所以大家都先sort再uniq# 统计每个IP出现次数 sort ip.txt | uniq -c # 按出现次数降序排列 sort ip.txt | uniq -c | sort -rnuniq -c输出格式是次数 内容从少到多排列再加一层sort -rn就变成内容 次数 倒序——这个组合就是统计Top N的标准姿势。uniq -d只显示重复行uniq -u只显示唯一行这两个参数在查重时很实用。6.3 diff和cmp文本差异与字节级比较diff逐行比较文本内容差异常用于对比两个配置文件、两份代码# 对比两个文件显示差异点 diff config_old.conf config_new.conf # 统一格式输出可读性更高 diff -u config_old.conf config_new.conf # 递归对比两个目录 diff -r dir1/ dir2/diff -u格式还是补丁文件的基础代码评审、配置变更说明时经常用。差异过多时diff输出会比较长加-q参数只显示哪些文件不同不显示具体差异先看整体影响面再深入细节。cmp做的是字节级对比它不关心文本结构只关心二进制数据是否一致。判断两个文件是否完全相同用cmp -s file1 file2 echo identical-s静默模式配合退出码0相同、1不同写脚本做自动化判断非常方便。6.4 经典日志分析组合拳把前面所有命令串起来是这套内容处理工具真正发力的时刻。统计一份access.log中访问量最大的前10个IPawk {print $1} /var/log/nginx/access.log | sort | uniq -c | sort -rn | head -n 10分步解释一下awk {print $1}把每行日志的第一列IP地址提取出来sort让相同IP的相邻排列为uniq做准备uniq -c统计每个IP出现次数sort -rn按次数从大到小排序-r倒序、-n数值比较head -n 10只取前10条这一行命令就是日志分析的基础单元无论是查访问来源、查接口错误率、查用户活跃都是同样的套路。它体现的核心思想是每个命令干一件小事管道让它们无缝衔接。7. 综合实战一条命令排查Nginx访问日志里的异常IP7.1 场景描述与分步拆解假设收到告警Nginx服务器流量异常某个IP在疯狂请求。需要快速定位这个IP以及它的请求特征。步骤一先看总访问量大致情况wc -l /var/log/nginx/access.log步骤二找出访问量最大的前10个IPawk {print $1} /var/log/nginx/access.log | sort | uniq -c | sort -rn | head -n 10步骤三锁定IP后查看这个IP具体请求了哪些路径、返回了什么状态码grep ^192.168.1.100 /var/log/nginx/access.log | awk {print $7, $9} | sort | uniq -c | sort -rn | head -n 20这里的grep用^开头锚定行首确保只匹配该IP开头的日志行。$7是请求路径$9是状态码。输出结果能直接看出它在请求什么资源、服务器给了什么响应。7.2 实时跟踪与自动屏蔽的延伸如果想实时观察这个IP还在干什么用tail -F加管道过滤tail -F /var/log/nginx/access.log | grep 192.168.1.100如果确认是恶意请求需要临时屏蔽可以结合iptables或者直接写个脚本检测。生产环境操作前先确认IP合法性避免误伤正常用户。排查这种问题时命令本身不难难的是思路要清晰先定位谁、再看做了什么、最后决定怎么处理。7.3 编码问题与查看CSV、数据文件的经验日志和配置文件看多了会经常遇到编码问题。除了前面说的file -i和iconv查看CSV文件时也容易踩坑。CSV文件如果是逗号分隔内容里又带了引号逗号简单用cut -d,就会拆错列。此时可以用python3 -c来做更精确的解析python3 -c import csv, sys for row in csv.reader(sys.stdin): print(row[0], row[3]) data.csv这是内容处理里一个重要的补充视角命令行工具解决80%的场景剩下的复杂解析交给脚本。判断标准很简单如果管道链条超过四五个且逻辑越来越绕就应该考虑用脚本了。7.4 如何快速记忆这些命令我不提倡死记硬背更有效的办法是场景驱动记忆。处理文件内容时默认问自己四个问题要看整体还是局部cat、less、head、tail要挑哪些行grep加条件sed按行号要不要拆列、统计awk、sort、uniq要不要改文件sed -i但记得先备份这些命令之间不是孤立的它们的组合能力远大于单独使用。实际工作中我很少单独用其中某一条基本都是管道串起来一稿解决。拿日志分析这行样本命令多练几遍熟练之后你会发现所谓Linux命令并不是一本本手册而是一套搭积木的思维。核心是知道自己手头有什么积木、每块积木的形状是什么剩下的就是按需拼接。把这些命令当工具而不是当考点用起来会顺很多。提示生产环境执行sed -i、awk这类有写入操作的命令前先在小样本文件上试跑一遍。宁可多花两分钟验证也不要大半夜把配置文件改废了再爬起来恢复。

读完文章,也想定制专属网站?

尧图设计师 24 小时内与您沟通定制方案

免费获取报价