0%

Linux 进阶常用命令实战:grep 与 sed 详解

在 Linux 日常开发与运维中,除了 cdlsmkdir 这些基础命令外,我们大部分时间都在与文本和日志打交道。

本文整理了 grep(文本搜索)和 sed(流编辑)在实际工作中的高频使用场景,涵盖日志故障排查、配置修改及数据清洗等操作。

🔍 一、grep 命令:查找与过滤

grep (Global Regular Expression Print) 是最强大的文本搜索工具,常用于日志分析代码搜索配置文件过滤

1. 场景一:故障排查与日志上下文分析

在排查线上故障(如 Java 应用的空指针异常)时,仅仅找到“Error”关键词是不够的,通常需要查看报错前后的堆栈信息。

示例:分析 NullPointerException

  • 查看报错及其后 50 行(定位堆栈)
    使用 -A (After) 参数可以显示匹配行之后的行,配合 less 分页查看,体验最佳。

    1
    grep -A 50 "java.lang.NullPointerException" a.log | less
  • 统计报错出现的次数
    快速评估故障严重程度,使用 -c (Count) 参数。

    1
    grep -c "java.lang.NullPointerException" a.log
  • 动态追踪报错日志
    结合 tail -f 实时监控。
    注意:当使用 -A 上下文参数配合管道流时,输出可能会有缓冲延迟。

    1
    tail -f a.log | grep -A 50 "java.lang.NullPointerException"

2. 场景二:实时监控与关键词过滤

在系统维护中,我们需要从不断滚动的海量日志中,实时“捞”出我们关心的信息。

目标 命令示例 解释
实时过滤包含 “Error” 的行 `tail -f server.log grep —line-buffered “Error”` --line-buffered 确保输出不被缓存,实时显示。
查找最近 500 行中特定 IP 的请求 `tail -n 500 access.log grep “192.168.1.1”` 组合使用,快速定位最近的访问记录。

3. 场景三:代码库与配置文件的快速搜索

在庞大的工程目录或 /etc 配置目录中,快速定位包含特定字符串的文件。

目标 命令示例 解释
递归查找代码中的关键词 grep -r -n "malloc" *.c -r 递归子目录查找,-n 显示行号,*.c 限定文件后缀。
查看有效的配置项(排除注释) grep -v "^#" config.conf -v 反向匹配,^# 正则匹配以 # 开头的行。常用于过滤掉大量注释。
精准查找完整单词 grep -i -w "port" settings.ini -i 忽略大小写,-w 强制全词匹配(避免匹配到 “portable” 等词)。

✂️ 二、sed 命令:文本替换与结构化修改

sed (Stream Editor) 是非交互式的流编辑器,最常用于批量修改配置文件数据清洗/格式化删除特定行

1. 场景一:批量替换字符串(配置文件修改)

这是 sed 的杀手级功能,特别适合在自动化部署脚本中使用,无需人工打开编辑器即可修改文件。

目标 命令示例 解释
全局替换并保存文件 sed -i 's/http/https/g' config.ini s/旧/新/g 是标准替换语法,g 代表全局替换。-i (in-place) 表示直接修改原文件。
仅替换特定行范围 sed '10,20s/user/admin/g' data.txt s 前添加 10,20,指定仅在第 10 到 20 行之间执行替换。
删除特定结尾的行 sed '/;$/d' script.js /;$/ 匹配以分号结尾的行,d 指令执行删除操作。

2. 场景二:数据清洗和格式重排

利用 sed 的扩展正则表达式和捕获组功能,可以对 CSV 或日志数据进行复杂的格式调整。

目标 命令示例 解释
交换 CSV 列的位置 sed -E 's/([^,]*),([^,]*),([^,]*)/\3,\2,\1/' file.csv -E 启用扩展正则。(...) 是捕获组,\1\2\3 分别引用捕获到的第一、二、三个字段,实现列的重排。
批量添加注释 sed 's/^/#/' file.txt ^ 匹配行首,将其替换为 #,从而快速注释掉整个文件的内容。

🖥️ 三、系统状态监控:topfree

当服务器变慢或负载报警时,首先要看的就是 CPU 和内存。

1. top:实时显示系统资源与进程

top 相当于 Linux 的任务管理器。

  • 常用操作:直接输入 top 回车。
  • 交互快捷键(进入 top 界面后按):
    • P (大写):按 CPU 使用率排序(找 CPU 飙高的进程)。
    • M (大写):按 内存 使用率排序(找吃内存的进程)。
    • 1 (数字):展开查看每个逻辑 CPU 核心的负载。
    • q:退出。

2. free:查看内存使用情况

查看服务器剩余内存最直观的命令。

目标 命令示例 解释
以人类可读格式查看(GB/MB) free -h -h (human-readable) 自动转换单位。重点关注 available 列(实际可用内存)。
每 3 秒刷新一次 free -h -s 3 -s 指定刷新间隔,用于监控内存变化趋势。

💾 四、磁盘空间管理:dfdu

磁盘满了会导致服务挂掉,这两个命令一个看“宏观”,一个看“微观”。

1. df:查看文件系统磁盘占用 (Disk Free)

用于检查整体磁盘分区是否已满。

目标 命令示例 解释
查看磁盘挂载点及使用率 df -h -h 显示易读格式(G/M)。重点看 Use%Mounted on
查看 inode 使用情况 df -i 有时磁盘空间没满但 inode 满了(小文件过多),也会导致无法写入。

2. du:查看文件/目录大小 (Disk Usage)

df 显示磁盘满了,用 du 来找出具体是哪个目录在占用空间。

目标 命令示例 解释
查看当前目录下每个子目录的大小 du -sh * -s (summary) 汇总大小,-h 易读格式,* 代表当前目录所有文件。非常高频的命令!
深度为 1 的目录下大小排序 `du -h —max-depth=1 sort -hr` 快速定位当前目录下最大的文件夹。

🌐 五、网络与进程快照:psnetstat

1. ps:查看进程快照

不同于 top 的实时监控,ps 用于查找特定的进程信息。

目标 命令示例 解释
查找特定服务(如 Java)进程 `ps -ef \ grep java` -ef 显示所有进程的全格式信息。配合 grep 查找 PID。
查看占用 CPU/内存 最高的 10 个进程 `ps aux —sort=-%cpu \ head -11` aux 显示更详细的用户和资源信息,head -11 显示表头+前10行。

2. netstat:网络端口查看

查看服务端口是否启动,或者查看是否存在大量异常连接。

注意:部分新系统可能需要安装 net-tools 或使用 ss 命令替代。

目标 命令示例 解释
查看所有监听中的 TCP/UDP 端口 netstat -tulpn -t (tcp), -u (udp), -l (listening), -p (显示进程名/PID), -n (不解析域名,直接显示IP)。
统计各类连接状态的数量 `netstat -n \ awk ‘/^tcp/ {++S[$NF]} END {for(a in S) print a, S[a]}’` 高级用法,用于分析 TCP 连接状态(如查看有多少 ESTABLISHEDTIME_WAIT 连接)。

📂 六、ls 命令:不仅仅是列出文件名

ls (List) 的核心价值在于排序信息展示。在杂乱的日志目录或磁盘清理时,合适的参数能让你一眼看到关键信息。

1. 场景一:按时间排序(找最新日志/文件)

这是运维中最常用的场景之一。当你进入 /var/log 目录,想知道哪个日志文件刚刚被修改过:

命令示例 解释
ls -lt -t修改时间排序(倒序,最新的在最上面)。
ls -lrt -r (reverse) 反向排序。推荐用法:最新的文件会显示在终端的最下方,不用滚轮就能直接看到。
ls --full-time 显示精确到毫秒的时间,用于排查并发文件生成的时间差。

2. 场景二:按大小排序(磁盘清理)

当磁盘报警时,需要快速找出当前目录下谁是“大胖子”:

命令示例 解释
ls -lhS -S (大写) 按文件大小排序(大文件在前)。-h (human) 将字节转换为 KB/MB/GB 显示。
`ls -lhS head -5` 只看最大的前 5 个文件。

3. 场景三:文件类型与隐藏文件

命令示例 解释
ls -a -a (all) 显示所有文件,包括以 . 开头的隐藏文件(如 .env, .ssh)。
ls -F 在文件名后追加符号标识类型:/代表目录,*代表可执行文件,@代表软链接。方便直观区分。

🐱 七、cat 命令:拼接与特殊查看

cat 的全称是 Concatenate (拼接),它的本意是将文件连接起来,查看内容其实是它的副作用。

1. 场景一:辅助排查与格式检查

直接查看代码或配置时,有时候肉眼看不出的格式问题(如多余的空格、Tab混用)会导致程序报错。

命令示例 解释
cat -n file.py -n (number) 显示行号。在根据报错日志(如 “Error at line 42”)定位代码时非常有用。
cat -b file.txt -b 也是显示行号,但跳过空行不编号。
cat -A config.conf -A (All) 显示所有隐藏字符。它会用 ^I 表示 Tab 键,用 $ 表示行尾。排查配置文件格式错误(如 YAML/Python 缩进问题)的神器

2. 场景二:文件合并与写入

利用 cat 的拼接特性,可以快速合并日志或创建小文件。

命令示例 解释
cat part1.log part2.log > full.log part1part2 的内容首尾连接,合并写入 full.log
cat > note.txt 快速创建文件。输入命令后,直接在终端输入内容,按 Ctrl+D 保存退出。
cat /dev/null > access.log 清空文件内容。将空设备重定向到日志文件,保留文件权限但清空内容(比 rm 安全)。

3. 补充:反向查看 tac

taccat 的反写,它的功能也是反的。

  • 命令tac error.log | less
  • 场景:将文件内容从最后一行到第一行倒序显示。当你只关心日志末尾最新的报错,但又想往前追溯一点时,比 tail 更灵活。

🔝 八、head & tail 命令:首尾截取

如果你只需要查看大型文件的开头或结尾(比如几万行的日志),而不希望让 cat 瞬间刷满屏幕,这两个命令是首选。

1. 场景一:快速预览与精确采样

命令示例 解释
head -n 20 data.csv 查看文件的前 20 行。常用于查看数据文件的表头。
tail -n 20 server.log 查看文件的最后 20 行。
tail -n +50 config.sh 从第 50 行开始显示一直到末尾。

2. 场景二:实时监控(故障排查核心)

命令示例 解释
tail -f access.log -f (follow) 实时追踪。屏幕会保持打开,只要有新日志写入,它就会立即显示。
tail -F service.log -F 更稳健。如果文件被重命名或由于日志轮转(Rotation)被删除重建,它能自动重连。

🔍 九、less 命令:优雅的分页浏览

如果说 cat 是“一泻千里”,那么 less 就是“精准漫游”。它是 Linux 中查看大文件最专业、最推荐的方式,因为它不需要一次性加载整个文件,速度极快。

1. 为什么用 less 而不是 cat

  • 内存友好:打开 10GB 的日志文件,cat 会导致系统卡死,而 less 秒开。
  • 交互性强:支持搜索、翻页、跳转,且不污染终端输出记录。

2. 交互快捷键(进入 less 后使用)

快捷键 功能
j / `k` 向下一行 / 向上一行(同 Vim)。
空格 / `b` 向下一页 (Forward) / 向上一页 (Backward)。
/关键词 向下搜索。输入后按 n 跳到下一个,按 N 跳到上一个。
?关键词 向上搜索
G / `g` 跳转到文件末尾 / 跳转到文件开头。
F 进入“实时追踪模式”(类似 tail -f),按 Ctrl+C 退出该模式回到浏览模式。
q 退出 (Quit)。

3. 命令组合

命令示例 解释
less -N file.py -N (Line Number) 在查看时显示行号。
`dmesg less`

🕵️ 十一、文件查找神器:find 与 locate

在 Linux 中找文件,主要靠这两个命令:一个“地毯式搜索”(find),一个“查索引”(locate)。

1. find:全能但较慢的实时搜索

find 直接扫描磁盘,功能最强大,支持按文件名、大小、时间、权限等各种条件查找。

目标 命令示例 解释
按文件名查找 find /etc -name "nginx.conf" /etc 目录下查找名为 nginx.conf 的文件。
忽略大小写查找 find . -iname "readme.md" -i (ignore case) 忽略大小写。
按文件类型查找 find . -type f -name "*.py" -type f (file) 只找文件,-type d (directory) 只找目录。
按文件大小查找 find / -size +100M 查找大于 100MB 的文件(+大于,-小于)。
按修改时间查找 find . -mtime -7 查找最近 7 天内被修改过的文件。

进阶:找到并执行操作 (-exec)

这是 find 最强大的功能,可以对找到的每个文件执行特定的命令。

  • 删除 30 天前的日志文件
    1
    find /var/log -name "*.log" -mtime +30 -exec rm {} \;
    解释:{} 代表找到的文件名,\; 是命令结束的标记。

2. locate:极速但有延迟的索引搜索

locate 不扫描磁盘,而是查询系统内置的文件数据库(通常位于 /var/lib/mlocate/mlocate.db)。

  • 优点:速度极快,毫秒级返回。
  • 缺点:新建的文件可能找不到(因为数据库通常每天自动更新一次)。
目标 命令示例 解释
快速查找文件 locate user_config 只要路径中包含 user_config // filepath: e:\blog\myblogs\source_posts\linux_cmd.md

// …existing code…

  • find 命令: find 命令的参数非常特殊,通常不遵循这种捆绑规则(如 find . -type f 不能写成 -tf)。

🕵️ 十、文件查找神器:find 与 locate

在 Linux 中找文件,主要靠这两个命令:一个“地毯式搜索”(find),一个“查索引”(locate)。

1. find:全能但较慢的实时搜索

find 直接扫描磁盘,功能最强大,支持按文件名、大小、时间、权限等各种条件查找。

目标 命令示例 解释
按文件名查找 find /etc -name "nginx.conf" /etc 目录下查找名为 nginx.conf 的文件。
忽略大小写查找 find . -iname "readme.md" -i (ignore case) 忽略大小写。
按文件类型查找 find . -type f -name "*.py" -type f (file) 只找文件,-type d (directory) 只找目录。
按文件大小查找 find / -size +100M 查找大于 100MB 的文件(+大于,-小于)。
按修改时间查找 find . -mtime -7 查找最近 7 天内被修改过的文件。

进阶:找到并执行操作 (-exec)

这是 find 最强大的功能,可以对找到的每个文件执行特定的命令。

  • 删除 30 天前的日志文件
    1
    find /var/log -name "*.log" -mtime +30 -exec rm {} \;
    解释:{} 代表找到的文件名,\; 是命令结束的标记。

2. locate:极速但有延迟的索引搜索

locate 不扫描磁盘,而是查询系统内置的文件数据库(通常位于 /var/lib/mlocate/mlocate.db)。

  • 优点:速度极快,毫秒级返回。
  • 缺点:新建的文件可能找不到(因为数据库通常每天自动更新一次)。
目标 命令示例 解释
快速查找文件 locate user_config 只要路径中包含 user_config

十一、参数捆绑

简单来说:在 Linux 中,大部分命令(尤其是传统的 C 语言编写的命令,如 ls, cat, grep, tail)是支持将单字母参数组合在一起的。

这种组合方式通常被称为 “Short Option Bundling”(短参数捆绑)

1. 组合规则

  • 必须是单字母参数: 只有带单个连字符(-)的单字母参数可以组合。
  • 长参数不可组合: 带两个连字符(--)的长参数(如 --verbose)必须独立编写。
  • 顺序通常不重要: 比如 ls -alls -la 效果是一样的。
  • 带值的参数除外: 如果某个参数后面需要紧跟一个值(比如 f 参数后面要跟文件名),它通常必须放在组合的最后一位

2. 常见示例

原始命令 组合后的命令 解释
ls -l -a -h ls -lah 以列表形式 (-l)、显示隐藏文件 (-a)、人类可读格式 (-h) 列出文件。
ps -e -f ps -ef 显示系统所有进程 (-e) 及完整格式 (-f)。
tar -c -v -f tar -cvf 创建 (-c) 详细过程 (-v) 的归档文件。注意:f 必须在最后,因为后面要接文件名。
cat -n -v cat -nv 显示行号 (-n) 并显示非打印字符 (-v)。

3. 特殊情况:带参数值的组合

这是一个非常重要的细节。如果一个参数需要指定具体的值,你不能把它放在中间。

❌ 错误示例:
tar -cfv my_archive.tar .
这里 f 后面本应跟着文件名,但因为 v 在它后面,系统会误以为文件名是 v

✅ 正确示例:
tar -cvf my_archive.tar .
或者直接分开写:
tar -cv -f my_archive.tar .

4. 为什么会有这种设计?

这是基于 POSIX 标准GNU 编码规范 的传统。在早期的计算机系统中,由于终端输入效率较低,开发者倾向于使用尽可能少的字符来触发复杂的任务。

5. 并不是所有命令都支持

虽然大部分基础命令(如 ls, cat, rm, cp)都支持,但也有例外:

  • Java 系列: java -version 看起来像短参数,但实际上它使用的是单个连字符引导的长单词,不能拆分(不能写成 java -v -e -r...)。
  • 部分现代工具: 一些用 Go 或 Rust 编写的新型 CLI 工具可能对参数解析有不同的逻辑。
  • find 命令: find 命令的参数非常特殊,通常不遵循这种捆绑规则(如 find . -type f 不能写成 -tf)。