☰
Linux文件查看与编辑命令实战:cat/less/sed/awk选型逻辑
2026/10/3 9:00:14 网站建设 项目流程

"cat一个几百MB的日志,终端直接卡死,光标闪了半天也没输出完"——这是我带过的每个新人几乎都会踩的第一脚。等他们手忙脚乱Ctrl+C之后,往往还会补一句"查看文件内容不就这么几个命令吗,能有多大区别"。区别确实很大,大到less和cat之间隔着一个"会不会用Linux系统常用命令"的分水岭。

这篇是Linux系统常用命令系列的第二篇,聚焦文件内容查看与编辑。我打算用最贴近实战的方式,把cat、less、head、tail、grep、vim、sed、awk这几组命令掰开揉碎。它们覆盖了日常排查日志、阅读配置、批量改文件的九成场景,也是面试题里反复出现的常客。无论你是刚转行过来的运维新人,还是被领导临时抓去处理服务器问题的开发,这篇都值得花二十分钟过一遍。读完你能建立起一套自己的选择逻辑:什么场景该用什么命令,为什么用它,以及用到什么程度就该换工具。

1. 文件查看的下限与上限:cat、less、head、tail的选择逻辑

很多人学Linux命令是背参数表,学到后面发现真正困难的不是记不住命令,而是拿到一个真实文件时不知道选哪个。所以这一章我先不罗列参数,而是讲清楚这几个命令各自的适用边界。

1.1cat只适合"小文件+要拼接"两类场景

cat的全称是concatenate,本意是拼接文件。cat a.txt b.txt > c.txt这种用法才是它的本职工作。在终端里直接cat一个文件只是它的附加功能,却被很多人当成了唯一功能。

如果你要看的文件只有几十行,比如刚写完的配置文件、浅浅几行的服务状态文件,那cat完全够了。加上-n参数还能显示行号,配合grep定位问题很快:

cat -n /etc/nginx/nginx.conf | head -50

但文件一旦超过几百行,或者单行内容特别长,cat的劣势就暴露了:内容一次性糊到屏幕上,头部直接滚出视野,你只能靠鼠标往上翻。更糟糕的是,如果你在SSH终端里误cat了一个二进制文件,终端可能直接乱码甚至假死。在服务器上cat二进制文件导致SSH会话异常,是运维事故里很低级但很常见的一种。

提示:cat还有一个容易被忽略的细节——它默认不会在文件结尾缺换行符时自动补一个。所以用cat拼接多个文件时,如果每个源文件末尾都没有换行,拼出来就会变成一整行。手动补换行通常是写脚本时的必修课。

1.2less是长文件阅读的正解,不是vim的平替

less这个名字来源于"less is more"——它是早期more命令的增强版。more只能往后翻,less可以前后翻,还能搜索、跳转,这基本覆盖了阅读长文件的全部需求。

打开一个几万行的大日志:

less app.log

进入less之后:

  • 按j或向下方向键逐行往下,按k或向上方向键往回看。
  • 按空格或Ctrl+f翻下一页,按Ctrl+b翻上一页。
  • 输入/关键词向下搜索,按n跳转到下一个匹配项,按N跳到上一个。
  • 输入G跳到文件末尾,输入gg回到开头。
  • 输入行号+G直接跳到指定行,比如100G就是去第100行。
  • 按q退出。

我排查线上问题时,less用得最多的场景是:先grep定位行号,然后less打开文件指定跳到那一段上下文。比如grep -n "error" app.log拿到行号是5321,那我直接less +5321 app.log就能精确定位到那一行,不要从头一页页翻。

less还有一个独特优势:打开大文件时它并不会把整个文件读进内存,而是按需读取,所以哪怕文件有几个GB,打开速度依然很快。这一点vim都做不到——vim打开大文件会明显卡顿,而less稳得很。

1.3head、tail负责"只看一头一尾"

head和tail的定位很明确:你只关心文件的开头几行或末尾几行,没必要打开整个文件。

查看一个服务最近有没有启动成功,最常用的就是tail:

tail -50 app.log

tail -f是日志跟踪的利器。-f会持续等待文件新增内容并直接打印,放着不管就能实时看到日志滚动:

tail -f app.log

如果还想过滤一下,配合grep即可:

tail -f app.log | grep "ERROR"

这里有个经验点:tail -f配合grep时,如果日志量特别大,可能追不上输出速度,导致漏数据。更好的做法是先用tail落一个快照文件再分析,或者直接用grep读文件而不是实时追流。生产环境要慎用tail -f,挂在前台占着终端不说,日志疯狂刷新时还会吃掉不少CPU和IO。

head的用法就简单了,默认看前10行,加上-n自定义行数:

head -20 /etc/nginx/nginx.conf

1.4 取中间某一段区间,用sed比用编辑器快得多

想取文件第100行到第200行,最直接的方式是sed -n '100,200p' file。这个放在后面跟sed一起细讲,但这里先说明:不要打开编辑器再翻过去,在终端里一条命令出结果,效率和体验完全是两个量级。

查看类命令还有个隐藏技巧:把多个命令串进管道,比如"只看文件第50行到第70行,并且去掉空行"。这种组合在排查配置时特别常用。

2. 查找与统计:grep配合wc -l、sort、uniq解决九成需求

文件查看了,接下来问题就来了:怎么从几万行日志里找到跟"报错"相关的那几行?如果这个动作你还靠肉眼滚动,那效率基本为零。grep就是干这个的,它是Linux系统常用命令里被使用频率最高的命令之一,我觉得没有之一。

2.1grep最常用的参数,按实用度排序

grep的参数很多,但日常高频使用的不超过10个。先不急着一口气全学,先把这几个记熟:

grep "关键词" 文件 grep -i "关键词" 文件 # 忽略大小写 grep -n "关键词" 文件 # 显示行号 grep -v "关键词" 文件 # 反向匹配,排除含关键词的行 grep -r "关键词" 目录 # 递归搜索目录下所有文件 grep -E "A|B" 文件 # 扩展正则,匹配A或B grep -l "关键词" 目录/* # 只列出含关键词的文件名

-n这个参数我建议养成条件反射,只要grep就加。因为拿到行号之后,你才能用sed或者less +行号去定位上下文。没有行号的grep结果就像房产中介只告诉你"小区很好"却不给你门牌号,参考价值大打折扣。

-v也是一个日常兜底神器。比如查看日志时想过滤掉那些"心跳"之类的骚扰信息:

grep -v "heartbeat" app.log | tail -20

2.2 统计出现次数:grep -c与管道结合

最简单的统计是grep -c,直接数匹配行数:

grep -c "ERROR" app.log

但要统计"有哪些不同的错误类型,各自出现多少次",grep -c就不够用了。这时候要用到三个命令的组合:

grep -oE "\[[A-Z]+\]" app.log | sort | uniq -c | sort -rn

这条命令的含义是:把日志里所有用中括号包起来的大写字母标签(比如[ERROR]、[WARN])全部抽出来,排序后去重统计次数,再按数字从大到小排序。这样一眼就能看出当天日志里哪种类型最多。

uniq有个重要前提:它只能去掉相邻的重复行。所以必须先sort再uniq,否则计数会错乱。这个坑我见过不少新人踩:单独uniq -c发现同样的词出现了好几行,百思不得其解,其实就是这个原因。

2.3 多文件搜索与二进制文件干扰

在多个文件里找内容,grep -r能递归处理目录,但它会把二进制文件也扫一遍,输出一堆乱码,甚至还会报"binary file matches"。处理办法是加-I,让grep跳过二进制文件;或者加--include限定只搜索某种后缀:

grep -rnI "TimeoutException" /opt/app/logs --include="*.log"

这里-I特指忽略二进制文件,跟-i忽略大小写仅差一个字母的大小写,容易混淆,我建议你实操一次把这两个参数都记住。

另一个多文件搜索的实用技巧:想找出哪几个配置文件里出现过某个关键词,就用-l:

grep -l "listen 443" /etc/nginx/conf.d/*

结果直接列出命中文件的名单,配合后续的vim逐一修改很顺手。

2.4find查找文件名,grep查找文件内容

很多初学者分不清find和grep的区别:find是按文件名、文件大小、修改时间等元信息找文件;grep是按内容找。两者配合使用的场景很典型——"在/data/logs目录下找到三天内修改过、且内容含有OutOfMemory的.log文件":

find /data/logs -name "*.log" -mtime -3 | xargs grep -l "OutOfMemory"

xargs在这里发挥的作用是:把find输出的一串文件路径,逐个或分批传给grep作为参数。这种串联模式在Linux系统常用命令里非常常见,文件查找和内容查找的任务往往是分不开的。

3. vim的三模式切换,新手最常卡住的点

如果你经历过在vim里怎么按都输不进去字、乱按键盘后文件内容突然变奇怪的阶段,那你已经踩过了几乎所有Linux新人都踩过的坑。vim的学习曲线是陡的,但它确实是Linux系统里绕不开的编辑工具。

3.1 先把三种模式刻进脑子

vim有且仅有三种模式:

  • 命令模式:启动vim默认所在模式,此时按键被视为命令,比如dd删一行、yy复制一行、p粘贴。在这个模式下输入文字只会被当成命令执行,不会写进文件。
  • 插入模式:按i进入,左下角会显示INSERT标识,此时所有输入都会写入文件。想退出插入模式,按Esc。
  • 末行模式:也叫底行模式,按:进入,在屏幕底部输入命令,比如:wq保存退出、:q!不保存退出、:%s/old/new/g全局替换。

新手最常卡住的场景是:不知道自己正处在哪个模式里。判定方法很简单——看左下角是否显示INSERT,有就是插入模式;按过一次Esc之后通常回到命令模式。

3.2 从打开文件到保存退出,一条最稳妥的路径

我推荐新手先建立最小可用操作集,别一上来就背快捷键,而是把这几个高频操作做成肌肉记忆:

vim 文件名

打开后:

  1. 按/关键词搜索定位,按n跳转下一个。
  2. 把光标移到要改的位置,按i进入插入模式。
  3. 修改完成后按Esc回到命令模式。
  4. 按Shift+;进入末行模式,输入wq回车保存退出。

万一改乱了,想放弃修改直接退出,就输入:q!,感叹号表示不保存强制退出。这个命令在面试题里几乎是必问的:如何不保存退出vim?答案就是q!。

3.3 高频操作速查

dd、yy、p这三个是我日常用得最多的:dd剪切当前行到缓存,yy复制当前行,p把缓存内容粘贴到当前行下方。组合用法比如:想把这行调整到下一行,直接dd到缓存,再移动光标到合适位置p。

多文件编辑时,:bn切换到下一个文件、:bp切回上一个文件。文件多到不想记顺序的时候,:ls可以列出所有已打开的文件,然后:b 数字直接跳过去。

提示:如果你用的是笔记本键盘,Esc键位置很远很别扭,可以在vim里配置把Ctrl+[当作Esc用,或者把J、K之类的键映射成Esc。这里不展开具体映射方法,但很多工程师都会在~/.vimrc里做这类优化。

3.4 大文件编辑的替代思路

vim打开100MB以上的文件会变得很慢,因为要构建语法高亮、撤销记录等结构。碰到这种情况,我的习惯是:先less快速浏览,确定要改哪几处之后再针对性地用sed原地修改,或者用vim的+行号直接跳过去改特定行,而不是一整个大文件平铺打开:

vim +行号 大文件.log

这个思路在运维日常里非常实用,也是Linux系统常用命令从"会用"到"用得聪明"的一个分水岭。

4. sed与awk,两条命令打通"批量编辑"和"字段提取"

如果说vim是手术刀,精细但一次只能处理一个点;那sed就是收割机,适合对大量文本做批量规整。awk则更像一个微型编程语言,专门干"按字段提取、汇总统计"的活。

4.1sed的原地修改与正则替换

sed最核心的用法之一是替换。命令格式是:

sed 's/旧内容/新内容/标志' 文件

标志位最常用g,代表全局替换;不写g的话,一行内只替换第一个匹配。

把文件里所有localhost换成127.0.0.1:

sed -i 's/localhost/127.0.0.1/g' app.conf

-i是原地修改,直接在原文件上生效,不加的话只会把替换后的结果打印到终端,原文件纹丝不动。刚学时我总忘加-i,改完发现文件没变,一度以为自己弄坏了什么。

在真正执行带-i的替换之前,务必先用不带-i的命令跑一遍,肉眼确认替换结果合理:

sed 's/192.168.1.1/192.168.2.1/g' app.conf

确认无问题之后再加上-i执行。生产环境如果连续误操作,可能直接让一个服务起不来,这个检查习惯真的能救命。

sed的删除也很常用。比如删除所有空白行:

sed '/^$/d' file

或者想删除从第5行到第10行的内容:

sed '5,10d' file

4.2awk处理字段提取,面试和实战双高频

awk的默认单位是"行",每行又被空格或制表符切成多个字段,$1是第一个字段,$2是第二个,$0是整行。它的结构是awk '{模式; 动作}',动作里可以写print等操作。

看一个经典场景——ps命令输出的进程列表,我想提取第二列的PID和最后一列的命令路径:

ps aux | awk '{print $2, $11}'

遇到分隔符不是空格的文件,比如/etc/passwd里用冒号分隔,可以用-F指定分隔符:

awk -F: '{print $1, $7}' /etc/passwd

这条命令打印的是用户名和登录shell。

awk还有内置变量和条件判断的能力。比如查看某日志里状态码是500的行的行数和行号:

awk '$9 == 500 {print NR, $0}' access.log

这里的$9是假设第9列是状态码,NR是当前行号,会打印出所有状态码为500的完整行和对应行号。条件里还可以用>、<、>=、!=这些比较运算符,基本上把它当一个小型查询语言用。

4.3sed适合作全局修改,awk适合按列提取,二者各自的地盘

很多人会纠结一个问题:一个任务到底用sed还是awk?

我的判断标准很简单:如果操作的对象是"行内的字符串内容",比如替换、删除匹配行、在指定行后插入内容,选sed;如果操作对象是"把一行拆成几列来筛选或汇总",选awk。两者经常配合使用——先用sed把无关内容排除,再用awk提取关键字段。

举一个综合例子:清理日志里所有时间戳前缀,然后按IP统计访问次数。

sed 's/^\[[0-9-]* [0-9:]*\]//' access.log | awk '{print $1}' | sort | uniq -c | sort -rn

一条管道干完四件事,这就是Linux命令行的魅力。

5. 大日志排查的综合实战:一次把命令全部串起来

讲了这么多命令,如果还停留在"单个命令单独用"的层面,那效率和没有系统性差不多。真实线上场景往往是多命令协作,这一章我用一个完整的例子把所有内容串一遍。

5.1 场景:Nginx访问日志里找出访问量最高的IP,以及它的最近请求

假设有一个access.log,Roughly长这个样子:

192.168.1.10 - - [21/Mar/2025:10:00:01 +0800] "GET /api/user HTTP/1.1" 200 523 192.168.1.11 - - [21/Mar/2025:10:00:03 +0800] "GET /api/order HTTP/1.1" 500 0 192.168.1.10 - - [21/Mar/2025:10:00:09 +0800] "POST /api/login HTTP/1.1" 200 321

第一步:统计前3个访问量最高的IP。

awk '{print $1}' access.log | sort | uniq -c | sort -rn | head -3

awk把第一列IP提取出来,sort排序后uniq -c统计次数,再sort -rn按次数从高到低排,最后head -3取前三。

第二步:找出这个IP最近发出了哪些请求。

grep "192.168.1.10" access.log | tail -20

于是我们看到的信息从"几十万行不知道哪行重要",变成了"目标地址精准打击",整个过程在秒级内完成。

5.2 场景:定位报错时间点附近的上下文

有的日志错误是持续性的,一条条看浪费时间。更好的思路是:先用grep -n拿到第一个错误出现的行号,再用sed取它的前后各20行看上下文。

grep -n "ERROR" app.log | head -1 # 假设输出: 2321: 2025-03-21 10:00:01 ERROR xxx sed -n '2301,2341p' app.log

这两条命令组合,相当于把事故现场前后40行完整“拉”出来。如果错误不止一个,还可以把所有"ERROR出现位置"的行号收集起来,循环读取上下文,不过这是脚本级的操作了,这里不展开。

5.3 生产环境里的三条操作禁忌

第一,绝对不要在不确定的情况下对生产配置文件执行带-i的sed命令,尤其是改正则替换时,一个不小心就把整文件内容改得面目全非。执行前先备份,或者先在不带-i的模式下预览输出。

第二,不要用cat直接查看大文件,原因前面已经说过了。如果非要用,至少先ls -lh看一眼文件大小。

第三,不要在一次命令里堆太多管道。命令写得太长确实看起来很厉害,但一旦某一步输出格式变化,这条命令就完全不可读了。如果真的需要复杂处理,我更建议存成脚本,而不是在命令行里写上百个字符的"一行流"。脚本还能重复使用,这个习惯长期来看非常值钱。

6. 面试爱问的几个细节题,顺便检验你对命令的理解

热搜词里出现了"linux面试题测试""linux命令大全手册""linux常用命令大全运维"这些关键词,说明有不少人是为了备战面试找资料。我在带新人和做技术面试时,常会挑几个细节问题来快速判断对方是不是真的用过、想过这些命令,而不只是看了一堆列表。

面试官常问的包括:cat和less的区别是什么?tail -f和tail -F的区别是什么?grep -E和grep的不同在哪?vim里怎么替换所有匹配的字符串?sed -i如果写错了怎么恢复?

其中tail -F这个点值得展开一点。-F会追踪文件描述符的变化,即使日志文件被轮转重命名了,tail -F也能重新跟随新的文件;而tail -f只跟随原文件描述符。在日常日志切割场景下,tail -F更适合长期跟踪。很多人在面试时能说出-f,但说不清-F,这恰好是考察有没有真正在日志轮转环境里调过手段的经历。

vim全局替换的命令是:%s/旧/新/g,%表示所有行,g表示一行内所有匹配项。如果只想替换部分行,可以把%换成行号范围,比如:5,20s/旧/新/g。

grep家族里面还有grep -A、grep -B和grep -C三个参数:-A显示匹配行之后的N行,-B显示之前N行,-C显示前后各N行。这个在看异常堆栈时特别有用:

grep -C 5 "NullPointerException" app.log

一次把异常抛出点前后的上下文都带出来。

这些细节并不难,但它们能体现你对命令的理解程度,远不是背几个参数能比的。我觉得准备面试时与其刷题,不如找一台机器把日志翻来覆去地查几遍,这些细节自然就进脑子了。

7. 把常用命令沉淀成自己的"命令手册"

写到这里,最后一个建议是:不要把Linux系统常用命令当成一次性学习,而是要建立自己的快速查阅系统。方法有两种,一种是把自己常用的命令积累到一个笔记文件里,遇到就补;另一种是在本地建一个命令速查脚本,比如写一个cheat.sh之类的自用工具。

我个人倾向于第一种。日常工作时多留心记录,比如处理完一次故障后,把当时用过的命令链整理到自己的笔记里,标注清楚每一步干什么。三个月后回看,这些都是比任何"命令大全"都实用的一手材料。

还有个小技巧:用history命令查看自己最近用过的命令记录,里面往往会沉淀出那些"不用思考就能敲出来"的高频命令。有意识地把这些命令里不熟悉的部分补一补,学习效率比啃整本手册高很多。

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询