1️⃣cat命令 – 在终端设备上显示文件内容
一、核心参数详解与使用场景
| 参数 | 全称/含义 | 使用场景 | 示例 |
|---|---|---|---|
-n | --number (行号) | 显示所有行的行号。用于查看代码、配置文件或日志时快速定位特定行。 | cat -n server.conf |
-b | --number-nonblank (非空行号) | 只对非空行编号。在查看代码时比 -n 更清爽,忽略空行。 | cat -b script.py |
-s | --squeeze-blank (压缩空行) | 将连续的多行空行压缩成一行。使输出更紧凑,便于阅读。 | cat -s logfile.txt |
-A | --show-all (显示所有) | 相当于 -vET,显示所有不可见的字符(如制表符、行尾符、换页符)。 | cat -A file_with_hidden_chars |
-T | (显示制表符) | 将制表符 (Tab) 显示为 ^I。用于检查代码缩进是空格还是Tab。 | cat -T script.py |
-E | --show-ends (显示行尾) | 在每行末尾显示 $ 符号。用于确认行是否结束,或查看是否有尾随空格。 | cat -E file.txt |
-v | --show-nonprinting (显示不可打印字符) | 使用 ^ 和 M- 符号显示不可打印字符(除了换行符和制表符)。 | cat -v binary_data.txt |
二、常用组合与实战场景
1. 查看与阅读文件(最基础用法)
# 查看一个文件的内容
cat filename.txt
# 查看多个文件的内容(按顺序连接显示)
cat file1.txt file2.txt
# 显示带行号的文件内容(阅读代码/日志神器)
cat -n application.log
# 显示带行号且忽略空行的文件内容(更清晰)
cat -b server.conf
2. 创建新文件或追加内容(无需文本编辑器)
# 1. 创建新文件并输入内容(输入完成后按 Ctrl+D 结束)
cat > new_file.txt
This is the first line.
This is the second line.
# [Ctrl+D]
# 2. 向已存在文件末尾追加内容
cat >> existing_file.txt
This line is appended to the end.
# [Ctrl+D]
场景:快速创建简单的配置文件、脚本或笔记,或者在脚本中动态生成文件。
3. 文件合并与重定向(核心功能)
# 将 file1 和 file2 合并成一个新文件 merged_file
cat file1.txt file2.txt > merged_file.txt
# 将 file3 的内容追加到 merged_file 的末尾
cat file3.txt >> merged_file.txt
# 将一个文件的内容覆盖到另一个文件(清空目标文件后写入)
cat source.txt > destination.txt
场景:合并多个日志文件、拆分后的大文件重组、备份配置等。
4. 诊断文件格式问题(高级技巧)
# 检查文件中是否包含Windows换行符(^M)或混合缩进
cat -A script.py
# 可能输出:This line has a Windows carriage return^M$
# 检查缩进是Tab还是空格(Tab会显示为 ^I)
cat -T index.html
# 输出:<div>^I<p>Hello</p>^I</div>
# 检查行尾是否有空格(空格会在 $ 前面显示)
cat -E document.txt
# 输出:This line has trailing spaces $
场景:在跨平台开发(Windows/Linux)时诊断编码和格式问题,保证脚本和配置文件的兼容性。
5. 管道组合(与其他命令协作)
cat 常被视为不必要的管道使用(Useless Use of Cat),因为许多命令可以直接读文件。但在某些场景下,从标准输入读取更灵活。
# 1. 将文件内容通过管道传递给处理命令(经典用法)
cat large_file.txt | grep "error" # 在文件中搜索关键词
cat access.log | sort | uniq -c # 排序并统计出现次数
# 2. 将文件内容作为另一个命令的输入
cat list_of_urls.txt | wget -i - # 下载文件中列出的所有URL
# 3. 与 here-document 结合,向交互式命令输入多行内容
cat <<EOF | mysql -u root -p
CREATE DATABASE mydb;
USE mydb;
EOF
三、注意事项与常见误区
-
不要用
cat查看大型文件- 问题:
cat会一次性输出整个文件内容到终端,如果文件巨大(如几个GB的日志),会导致终端卡死或刷屏。 - 解决方案:使用分页工具
less(推荐)或more。less huge_file.log # 可上下翻页、搜索、退出后不留屏幕垃圾 more huge_file.log # 基础分页
- 问题:
-
避免“无用的cat”(Cat Abuse)
- 不推荐:
cat file | grep "pattern"(多了一个不必要的进程) - 推荐:
grep "pattern" file(更高效,直接由grep读取文件) - 例外:当需要多个源的数据时,
cat管道很有用:cat file1 file2 | grep "pattern" # 从两个文件中搜索
- 不推荐:
-
谨慎处理二进制文件
cat可以输出二进制文件(如图片、压缩包),但输出到终端会导致乱码,甚至终端会话崩溃。- 用途:通常用于二进制文件的合并或重定向,而不是查看。
cat picture_part1 picture_part2 > complete_picture.jpg
四、常用组合速查表
| 场景 | 命令组合 | 说明 |
|---|---|---|
| 查看代码/配置 | cat -n filename | 带行号查看 |
| 检查格式 | cat -A filename | 显示所有隐藏字符 |
| 检查缩进 | cat -T filename | 显示Tab为^I |
| 合并文件 | cat file1 file2 > merged | 合并为新文件 |
| 追加内容 | cat >> file + 输入 | 追加到文件末尾 |
| 快速创建 | cat > file + 输入 | 创建新文件 |
| 管道输入 | cat file | command | 将文件内容传给其他命令 |
2️⃣grep命令 – 强大的文本搜索工具
一、核心参数详解与使用场景
1. 匹配控制参数(决定搜索什么)
| 参数 | 全称/含义 | 使用场景 | 示例 |
|---|---|---|---|
-i | --ignore-case (忽略大小写) | 大小写不敏感搜索。用于搜索不确定大小写的单词(如 “error”, “Error”, “ERROR”)。 | grep -i "error" logfile.txt |
-v | --invert-match (反向匹配) | 只显示不包含匹配模式的行。用于排除噪音,查找异常。 | grep -v "DEBUG" app.log (排除DEBUG行) |
-w | --word-regexp (单词匹配) | 只匹配完整的单词,而不是单词的一部分。防止误匹配(如从 background 中匹配 back)。 | grep -w "root" /etc/passwd |
-x | --line-regexp (行匹配) | 只匹配整行完全符合模式的行。常用于精确匹配配置文件中的设置。 | grep -x "PORT=8080" config.env |
-e PATTERN | --regexp=PATTERN (模式) | 明确指定一个搜索模式。主要用于搜索以 - 开头的模式,或指定多个模式。 | grep -e "-v" -e "-i" script.sh |
-f FILE | --file=FILE (文件) | 从文件中读取要搜索的模式(每行一个模式)。用于搜索一大组预定义的字符串。 | grep -f search_terms.txt big_file.txt |
-P | --perl-regexp (Perl正则) | 使用功能强大的 Perl 兼容正则表达式 (PCRE)。支持 \d, \s, 非贪婪匹配 .*? 等高级特性。 | grep -P "\d{3}-\d{4}" contacts.txt (匹配电话号码) |
2. 输出控制参数(决定如何显示结果)
| 参数 | 全称/含义 | 使用场景 | 示例 |
|---|---|---|---|
-n | --line-number (行号) | 显示匹配行所在文件中的行号。用于快速定位,尤其是在代码或日志文件中。 | grep -n "Exception" error.log |
-c | --count (计数) | 只显示匹配行的数量,而不是行本身。用于统计出现次数。 | grep -c "GET" access.log (统计GET请求次数) |
-o | --only-matching (只输出匹配部分) | 只输出匹配到的文本部分,而不是整行。用于提取特定格式的字符串。 | grep -oP 'src="\K[^"]+' page.html (提取图片URL) |
-q | --quiet / --silent (静默) | 静默模式。不输出任何结果,只根据是否找到匹配行设置退出状态码 ($?)。主要用于脚本中的条件判断。 | if grep -q "FATAL" log; then echo "Found error"; fi |
-a | --text (文本) | 将二进制文件视为文本文件来处理。用于在二进制文件中搜索文本字符串。 | grep -a "text" binary_file |
-H / -h | --with-filename / --no-filename (显示/隐藏文件名) | -H:强制显示文件名(默认在多文件搜索时显示)。-h:强制隐藏文件名。 | grep -H "pattern" file1 file2 |
--color=auto | (颜色) | 对匹配到的文本进行高亮显示。极大地提高可读性。推荐在 ~/.bashrc 中设置别名 alias grep='grep --color=auto'。 | grep --color=auto "TODO" *.py |
3. 上下文控制参数(显示匹配行周围的内容)
| 参数 | 全称/含义 | 使用场景 | 示例 |
|---|---|---|---|
-C NUM | --context=NUM (上下文) | 显示匹配行及其前后各 NUM 行。提供上下文,便于理解。 | grep -C 2 "crash" logfile (显示崩溃前后2行) |
-B NUM | --before-context=NUM (前上下文) | 只显示匹配行及其前面 NUM 行。 | grep -B 3 "Error:" logfile (查看错误发生前的日志) |
-A NUM | --after-context=NUM (后上下文) | 只显示匹配行及其后面 NUM 行。 | grep -A 5 "Starting process" logfile (查看启动后的输出) |
4. 文件选择参数(决定在哪里搜索)
| 参数 | 全称/含义 | 使用场景 | 示例 |
|---|---|---|---|
-r | --recursive (递归) | 递归搜索指定目录下的所有文件。用于在项目目录或日志目录中全局搜索。 | grep -r "function_name" /src/ |
-R | (同上,但遵循符号链接) | 同 -r,但会递归到符号链接指向的目录。 | grep -R "deprecated" /usr/include/ |
--include=GLOB | (包含文件) | 在递归搜索时,只搜索文件名匹配 GLOB 模式的文件。用于限制文件类型。 | grep -r --include="*.js" "console.log" . |
--exclude=GLOB | (排除文件) | 在递归搜索时,排除文件名匹配 GLOB 模式的文件。用于忽略特定文件。 | grep -r --exclude="*.min.js" "function" . (排除压缩的JS文件) |
--exclude-dir=DIR | (排除目录) | 在递归搜索时,排除名为 DIR 的目录。用于跳过 .git, node_modules 等目录。 | grep -r --exclude-dir=.git "pattern" . |
二、常用组合与实战场景
1. 日志分析(最经典场景)
# 查找所有ERROR日志,并显示行号和高亮
grep -n --color=auto "ERROR" application.log
# 查看ERROR日志及其后10行上下文(查看错误堆栈)
grep -A 10 "ERROR" application.log
# 统计不同HTTP状态码的出现次数
grep -oP 'HTTP/1.\d" \K\d{3}' access.log | sort | uniq -c
# 查找过去一小时内产生的日志(结合find)
find /var/log -name "*.log" -mmin -60 -exec grep -l "Fatal" {} \;
2. 代码开发
# 在项目中递归搜索所有使用某个函数的文件(排除二进制文件)
grep -rn --include="*.py" "def calculate" /myproject/
# 搜索TODO或FIXME注释
grep -rn --color=auto "TODO\|FIXME" src/
# 查找所有包含特定头文件的C文件
grep -l "#include <openssl/sha.h>" *.c
# 精确查找一个变量名,避免找到函数名或注释(-w单词匹配)
grep -wn "count" *.c
3. 系统管理与审计
# 检查密码为空的账户(反向匹配)
grep -v ':\*:\|:\!:' /etc/shadow | grep -v ':\$'
# 查找所有可执行文件(SUID/SGID)
find / -type f -perm /6000 2>/dev/null | grep -v "/proc/"
# 检查网络连接状态(ESTABLISHED)
netstat -tulnap | grep -E "(ESTABLISHED)"
4. 数据提取与处理
# 从HTML中提取所有URL
grep -oP '(?<=href=")[^"]*' webpage.html
# 提取所有IPv4地址
grep -oE "\b([0-9]{1,3}\.){3}[0-9]{1,3}\b" file.txt
# 提取所有邮箱地址
grep -oE "\b[A-Za-z0-9._%+-]+@[A-Za-z0-9.-]+\.[A-Z|a-z]{2,}\b" contacts.txt
5. 高级递归搜索组合
# 在Java文件中搜索,但排除test目录和所有jar包
grep -r --include="*.java" --exclude-dir=test --exclude="*.jar" "ArrayList" .
# 在多个目录中搜索多个模式,显示文件名和行号
grep -rn -e "pattern1" -e "pattern2" /path1/ /path2/
三、性能优化与注意事项
-
固定字符串搜索 (
-F)- 如果你的模式是简单的字符串,没有正则元字符(如
.,*,[]),使用-F(或fgrep) 会更快,因为它会禁用正则引擎。
- 如果你的模式是简单的字符串,没有正则元字符(如
-
减少搜索范围
- 使用
--include和--exclude系列参数可以大幅提升递归搜索的速度,避免搜索无关文件(如*.min.js,*.zip,.git/)。
- 使用
-
避免在根目录
/下递归grep -r pattern /会搜索整个硬盘,包括虚拟文件系统(如/proc,/sys),导致性能极差和大量错误。总是使用2>/dev/null或指定具体路径。
-
理解正则表达式
grep的威力在于正则。学习基础正则(BRE)和扩展正则(ERE-E或 PCRE-P)能极大提升你的搜索能力。- 常用元字符:
.,*,+,?,[],[^],^,$,|,(),\d,\s,\K(零宽断言)。
总结:高频组合速查表
| 场景 | 推荐命令组合 | 说明 |
|---|---|---|
| 基础搜索 | grep -n --color=auto "pattern" file | 带行号和高亮 |
| 忽略大小写 | grep -i "pattern" file | 大小写不敏感 |
| 统计次数 | grep -c "pattern" file | 只显示匹配行数 |
| 递归搜索代码 | grep -rn --include="*.ext" "pattern" dir/ | 在指定类型文件中搜索 |
| 查看上下文 | grep -C 3 "pattern" file | 查看匹配行前后3行 |
| 提取数据 | grep -oP "regex_pattern" file | 只输出匹配到的部分 |
| 脚本判断 | if grep -q "pattern" file; then ... | 静默模式用于条件判断 |
| 排除噪音 | grep -v "unwanted_pattern" file | 反向匹配,排除不需要的行 |
4️⃣tail命令 – 查看文件尾部内容
tail 命令是 Linux 系统管理和日志查看中使用频率最高的命令之一。它的核心功能是显示文件的末尾部分内容,尤其擅长实时监控不断增长的文件(如日志文件)。
以下是 tail 命令的参数详解、使用场景和经典组合。
一、核心参数详解与使用场景
| 参数 | 全称/含义 | 使用场景 | 示例 |
|---|---|---|---|
-n NUM / -NUM | --lines=NUM (行数) | 显示文件最后的 NUM 行。这是最常用的参数。省略 -n,直接使用 -数字 是常见简写。 | tail -n 50 file.log tail -50 file.log (显示最后50行) |
-f | --follow (跟随) | 实时监视文件尾部内容,并在新内容追加到文件时持续输出。日志监控神器。 | tail -f /var/log/syslog |
-F | (跟随 by-name) | 类似 -f,但更强大。它会跟踪文件名而非文件描述符。即使文件被轮转/切割/删除重建,它也能继续跟踪。监控日志的首选参数。 | tail -F /var/log/nginx/access.log |
-c NUM | --bytes=NUM (字节数) | 显示文件最后的 NUM 个字节。用于查看固定大小的尾部内容,尤其是二进制文件。 | tail -c 1024 data.bin (显示最后1KB) |
-q | --quiet / --silent (静默) | 当查看多个文件时,不显示每个文件的文件名标题。用于合并查看多个文件的尾部。 | tail -q -n 5 file1.log file2.log |
-v | --verbose (详细) | 当查看多个文件时,总是显示每个文件的文件名标题。 | tail -v -n 5 *.log |
--pid=PID | (进程ID) | 与 -f 联用,当指定进程 PID 终止后,自动退出 tail 命令。用于监控由特定进程生成的日志。 | tail -f --pid=$(pgrep myapp) myapp.log |
-s SEC | --sleep-interval=SEC (间隔) | 与 -f 联用,设置检查文件更新的时间间隔(默认为1.0秒)。降低监控频率以减少系统负载。 | tail -f -s 5 file.log (每5秒检查一次) |
二、常用组合与实战场景
1. 日志查看与监控(最核心场景)
# 1. 快速查看日志的最后10行(默认行为)
tail /var/log/syslog
# 2. 查看日志的最后100行
tail -n 100 /var/log/nginx/access.log
# 3. 实时监控日志文件(最常用组合)
tail -f /var/log/auth.log
# 按 Ctrl+C 终止监控
# 4. 实时监控并显示行号(方便定位)
tail -f -n 50 /var/log/app.log | nl
# 5. 强力实时监控(应对日志轮转 - log rotation)
# 如果使用 `-f`,当日志从 access.log 轮转为 access.log.1 时,跟踪会停止。
# 使用 `-F` 可以持续跟踪新生成的 access.log 文件。
tail -F /var/log/nginx/access.log
场景:实时调试应用程序、监控系统安全(登录尝试)、分析Web流量。
2. 组合过滤与实时分析(超级实用)
tail 的强大之处在于能与 grep, awk, cut 等命令组合,形成强大的实时分析管道。
# 1. 实时监控并只显示包含 "ERROR" 的行
tail -f app.log | grep --line-buffered "ERROR"
# `--line-buffered` 确保 grep 结果实时输出,而非缓存后输出
# 2. 实时监控并高亮关键词
tail -f app.log | grep --color=auto -E "ERROR|WARN|INFO"
# 3. 实时监控并提取特定字段(例如,从JSON日志中提取状态码)
tail -f api.log | grep -oP '"status":\s*\K\d+'
# 4. 实时监控并统计(例如,统计5秒内的500错误数)
tail -f -s 5 access.log | grep -c " 500 "
# 注意:这每5秒输出一个数字,表示过去5秒内500错误的次数
3. 对比与检查文件
# 1. 静默查看多个文件的最后几行(不显示文件名)
tail -q -n 3 file1.txt file2.txt
# 2. 详细查看多个文件的最后几行(显示文件名)
tail -v -n 3 *.config
# 3. 查看文件的最后1K内容(常用于检查文件是否完整结尾)
tail -c 1024 large_file.bin > last_kb.bin
4. 高级用法与脚本结合
# 1. 监控日志,并在出现特定关键词时触发操作(邮件/脚本)
tail -f /var/log/daemon.log | while read line; do
if echo "$line" | grep -q "Fatal Error"; then
echo "$line" | mail -s "ALERT on $(hostname)" admin@example.com
fi
done
# 2. 监控一个由特定进程创建的日志文件,进程退出则停止监控
APP_PID=$(pgrep -f "my_application")
tail -f --pid=$APP_PID /tmp/my_application.log
# 3. 从指定行开始显示(使用 `sed` 或 `awk` 辅助)
# 显示从第1000行到文件末尾的内容(相当于 `tail -n +1000`)
sed -n '1000,$p' huge_file.log
三、tail -f 与 tail -F 的区别(重要!)
这是 tail 命令最关键的一个知识点。
-
tail -f(follow descriptor):- 跟踪的是文件的描述符 (inode)。
- 优点:即使文件被重命名(如
mv logfile.log logfile.log.old)或删除,只要仍有进程持有该文件的描述符(如仍在运行的Web服务器),-f就能继续读取内容。 - 缺点:当日志轮转发生时(如
logrotate将access.log重命名为access.log.1并新建一个access.log),-f会继续跟踪旧的access.log.1(因为inode没变),而不会跟踪新的access.log。
-
tail -F(follow name):- 跟踪的是文件的名字。
- 行为:它会定期检查文件是否被删除或重建。如果文件名字被重新创建(如日志轮转后新建了一个同名日志文件),它会自动重新打开新文件并继续跟踪。
- 场景:几乎总是你应该用于监控日志的参数,因为它能优雅地处理日志轮转。
结论:在监控可能被轮转的日志时,始终使用 tail -F。
四、常用组合速查表
| 场景 | 命令组合 | 说明 |
|---|---|---|
| 查看日志结尾 | tail -n 100 file.log | 查看最后100行 |
| 实时监控日志 | tail -f file.log | 基本实时监控 |
| 实时监控(支持轮转) | tail -F file.log | 生产环境推荐 |
| 监控并过滤 | tail -F app.log | grep "ERROR" | 只看错误信息 |
| 监控并高亮 | tail -F app.log | grep --color "WARN" | 高亮警告信息 |
| 查看多个文件 | tail -v -n 5 *.log | 查看每个日志最后5行并显示文件名 |
| 轻量级监控 | tail -f -s 2 file.log | 每2秒检查一次更新,降低负载 |
总结与最佳实践
- 默认习惯:查看日志时,养成先看最后几行 (
tail -n 50) 的习惯,快速了解最新状态。 - 监控首选:需要实时监控时,总是使用
tail -F而不是tail -f,以应对日志轮转。 - 组合利器:将
tail -F与grep,awk,cut等命令通过管道结合,是系统调试和日志分析的王牌技巧。 - 谨慎操作:
tail是只读命令,相对安全。但在脚本中使用管道组合时,确保后面的命令不会意外阻塞或产生非预期操作。
5️⃣sed命令 – 批量编辑文本文件
sed (Stream Editor) 是 Linux 中最强大、最常用的文本处理工具之一。它以其非交互式和基于正则表达式的特性而闻名,特别适合在脚本中执行批量文本替换、删除、提取等操作。
理解 sed 的核心在于理解它的 [地址]命令 语法。地址 用于指定要操作的行,命令 指定要执行的操作。
一、核心参数详解与使用场景
1. 执行方式参数
| 参数 | 全称/含义 | 使用场景 | 示例 |
|---|---|---|---|
-e script | --expression=script (表达式) | 添加要执行的 sed 脚本命令。用于在命令行中执行多个操作。 | sed -e 's/foo/bar/' -e '/baz/d' file.txt |
-f script-file | --file=script-file (文件) | 从文件中读取 sed 脚本命令。当命令非常复杂或需要重复使用时。 | sed -f commands.sed file.txt |
-i[SUFFIX] | --in-place[=SUFFIX] (原地编辑) | 直接修改源文件。这是最危险的参数,也是最常用的之一。SUFFIX 用于在修改前创建备份。 | sed -i.bak 's/old/new/g' file.txt (创建备份后修改) sed -i '' 's/old/new/g' file (macOS 下无备份修改) |
-n | --quiet / --silent (静默) | 禁止自动打印模式空间。通常与 p 命令结合,只打印被处理过的行。 | sed -n '10p' file (只打印第10行) |
2. 常用 sed 命令 (在 -e 或脚本中使用)
| 命令 | 功能 | 使用场景 | 示例 |
|---|---|---|---|
s/regexp/replacement/flags | 替换 (Substitute) | 最常用的命令。将匹配 regexp 的文本替换为 replacement。 | sed 's/foo/bar/g' file.txt |
d | 删除 (Delete) | 删除匹配的行。 | sed '/pattern/d' file.txt |
p | 打印 (Print) | 打印当前模式空间。通常与 -n 参数一起使用。 | sed -n '/pattern/p' file.txt |
a\text | 追加 (Append) | 在指定行后面追加一行 text。 | sed '3a\This is new line' file.txt |
i\text | 插入 (Insert) | 在指定行前面插入一行 text。 | sed '1i\This is the first line' file.txt |
c\text | 更改 (Change) | 用 text 替换匹配的行。 | sed '/old_line/c\This is the new line' file.txt |
y/src/dst/ | 转换 (Transform) | 类似 tr 命令,将 src 中的字符逐个转换为 dst 中的字符。 | sed 'y/abc/ABC/' file.txt (a->A, b->B, c->C) |
q | 退出 (Quit) | 在处理完指定行后立即退出 sed,不再处理后续行。用于提取文件开头部分。 | sed '10q' file.txt (打印前10行,类似 head) |
3. 地址定址 (决定对哪些行进行操作)
| 地址格式 | 含义 | 示例 |
|---|---|---|
n | 数字,指定第 n 行 | sed '5d' file (删除第5行) |
$ | 最后一行 | sed '$d' file (删除最后一行) |
/regexp/ | 匹配正则表达式的行 | sed '/^#/d' file (删除所有注释行) |
n,m | 从第 n 行到第 m 行 | sed '10,20d' file (删除10到20行) |
n,+m | 从第 n 行到第 n+m 行 | sed '10,+5d' file (删除10到15行) |
n~m | 从第 n 行开始,每隔 m 行操作一次 | sed '1~2d' file (删除所有奇数行) |
$! | 除了最后一行之外的所有行 | sed '$!d' file (只保留最后一行) |
4. 替换命令 (s///) 的标志 (flags)
| 标志 | 功能 | 示例 |
|---|---|---|
g | 全局替换。替换行内所有匹配项,而不仅仅是第一个。 | sed 's/ /,/g' file (将所有空格替换为逗号) |
p | 打印。如果替换成功,则打印该行。常与 -n 联用。 | sed -n 's/pattern/replacement/p' file |
w file | 写入。将替换成功的行写入到指定文件。 | sed 's/pattern/replacement/w newfile.txt' file |
i 或 I | 忽略大小写 (GNU sed 扩展)。 | sed 's/foo/bar/i' file (匹配 FOO, Foo, foO 等) |
数字 | 替换第 N 个匹配项。 | sed 's/ /,/2' file (只替换每行的第二个空格) |
二、常用组合与实战场景
1. 文本替换 (最核心功能)
# 1. 将文件中所有 "apple" 替换为 "orange" (只输出到屏幕,不修改文件)
sed 's/apple/orange/g' file.txt
# 2. 直接修改源文件 (极其危险,务必先测试无 -i 的命令)
sed -i.bak 's/old_string/new_string/g' important_file.cfg
# 先备份 original_file.cfg.bak, 然后修改 original_file.cfg
# 3. 替换每行第2次出现的 "cat" 为 "dog"
sed 's/cat/dog/2' file.txt
# 4. 使用不同的分隔符 (当模式或替换内容包含 `/` 时非常有用)
sed 's|/usr/local|/opt|g' path.conf # 使用 | 作为分隔符
sed 's#/old/path#/new/path#g' file # 使用 # 作为分隔符
# 5. 使用分组反向引用 (提取和重用部分模式)
echo "Hello World" | sed 's/\(Hello\) \(World\)/\2 \1/'
# 输出: World Hello (交换了两个单词的位置)
# 现代 sed 支持 -E 选项使用扩展正则,避免转义括号
sed -E 's/(Hello) (World)/\2 \1/'
2. 行内容编辑 (删除、插入、追加)
# 1. 删除所有空行
sed '/^$/d' file.txt
# 2. 删除所有注释行 (以 # 开头的行)
sed '/^#/d' config.conf
# 3. 删除包含 "debug" 的行
sed '/debug/d' script.sh
# 4. 在第3行后追加一行文本
sed '3a\This line is added after line 3' file.txt
# 5. 在文件开头插入一行
sed '1i\This is the new first line' file.txt
# 6. 在匹配到 "SERVERNAME" 的行后追加配置
sed '/SERVERNAME/a\127.0.0.1 example.com' /etc/hosts
3. 文本提取与过滤 (类似 grep)
# 1. 打印包含 "error" 的行 (类似 grep)
sed -n '/error/p' system.log
# 2. 打印第10到第20行 (类似 sed -n '10,20p' 或 head -20 | tail -11)
sed -n '10,20p' large_file.txt
# 3. 打印从匹配 "START" 的行到匹配 "END" 的行之间的内容
sed -n '/START/,/END/p' data.txt
# 4. 只打印匹配行的上一行 (使用保持空间的高级技巧)
sed -n '/pattern/{x;p;d}; x' file.txt
4. 文件原地修改与备份 (脚本中的经典用法)
# 1. 安全修改:先备份原文件(.bak),再修改
sed -i.bak 's/old/new/g' file1.txt file2.txt
# 2. 为所有 .txt 文件的行尾添加分号
for f in *.txt; do
sed -i 's/$/;/' "$f"
done
# 3. 移除Windows文件中的回车符 (^M)
sed -i 's/\r$//' script.sh # 从 Windows 拷贝到 Linux 后的必要操作
5. 高级技巧与复杂脚本
# 1. 多重操作:先删除空行,再替换文本,最后删除注释行
sed -e '/^$/d' -e 's/foo/bar/g' -e '/^#/d' file.txt
# 2. 使用标签进行条件分支(很少用,但功能强大)
sed '{:start /pattern/{s/foo/bar/; p; d;}; /anotherpattern/b start}' file.txt
# 3. 将多个sed命令写入文件,然后执行
# commands.sed 内容:
# /^#/d # 删除注释行
# s/old/new/g # 全局替换
sed -f commands.sed input.txt
三、注意事项与最佳实践
-
-i参数是危险的:它会直接修改源文件。永远先在不带-i的情况下测试你的 sed 命令,确认输出无误后再使用-i。使用-i.bak创建备份是一个好习惯。 -
正则表达式贪婪性:
sed默认使用贪婪匹配。例如s/.*://会删除直到最后一个冒号的所有内容,而不是第一个。 -
平台差异:
- GNU sed (Linux) 功能最丰富,支持
\t,\n等转义和-i不带参数。 - BSD sed (macOS) 要求
-i ''才能进行无备份的原位编辑,且某些扩展(如\t)可能不被支持。在 macOS 上,建议使用gsed(GNU sed)。
- GNU sed (Linux) 功能最丰富,支持
-
性能考量:对于处理非常大的文件,
sed非常高效,因为它是流式编辑器,不会一次性将整个文件加载到内存中。 -
与
awk的选择:- 对于简单的行内替换和删除,
sed更简洁。 - 对于基于列的文本处理、计算和更复杂的逻辑,
awk通常是更好的选择。
- 对于简单的行内替换和删除,
总结:高频组合速查表
| 场景 | 命令组合 | 说明 |
|---|---|---|
| 简单替换 | sed 's/old/new/g' file | 全局替换 |
| 直接修改文件 | sed -i.bak 's/old/new/g' file | 备份后修改 |
| 删除空行 | sed '/^$/d' file | 删除所有空行 |
| 删除注释行 | sed '/^#/d' file | 删除以 # 开头的行 |
| 提取特定行 | sed -n '10p' file | 只打印第10行 |
| 提取范围行 | sed -n '10,20p' file | 打印10到20行 |
| 文件末尾追加 | sed '$a\new line' file | 在最后一行后追加 |
| 移除Windows回车 | sed -i 's/\r$//' winfile.txt | 转换DOS格式为UNIX格式 |
6️⃣vi命令 – 文本编辑器
vi(及其增强版 vim)是 Linux 和 Unix 系统中最经典、最强大的文本编辑器。它以其高效率(完全键盘操作)和无处不在(预装在几乎所有类 Unix 系统中)而著称。
学习 vi 的关键在于理解其模式概念和将命令组合起来的哲学。以下是其核心参数、模式、命令和组合的详细解析。
一、启动参数与使用场景
这些参数主要在命令行中启动 vi / vim 时使用。
| 参数 | 全称/含义 | 使用场景 | 示例 |
|---|---|---|---|
+[n] | (直接跳转) | 启动后直接将光标定位到第 n 行。用于快速修复特定行的错误。 | vi +10 script.py (打开并跳至第10行) |
+/pattern | (直接搜索) | 启动后直接搜索并定位到第一个匹配 pattern 的地方。用于快速找到特定内容。 | vi +/function app.js (打开并搜索"function") |
-R | (只读模式) | 以只读模式打开文件。防止意外修改重要文件。等同于 view 命令。 | vi -R /etc/fstab |
-r | (恢复模式) | 恢复因意外退出来保存的交换文件。用于文件恢复。 | vi -r myfile.txt (列出可恢复的交换文件) vi -r |
-c 'command' | (执行命令) | 启动后立即执行指定的 ex 模式命令。用于自动化初始操作。 | vi -c 'set number' -c 'syntax on' file.c (打开显示行号和语法高亮) |
-o[N] | (水平分割) | 水平分割窗口打开多个文件。N 指定窗口数。 | vi -o2 file1.txt file2.txt (水平打开两个文件) |
-O[N] | (垂直分割) | 垂直分割窗口打开多个文件。N 指定窗口数。 | vi -O3 app.js style.css index.html (垂直打开三个文件) |
二、核心模式:vi 高效之魂
vi 的操作围绕几个不同的模式展开,这是初学者最需要适应的地方。
| 模式 | 进入方式 | 退出方式 | 用途 |
|---|---|---|---|
| 普通模式 (Normal) | 启动默认模式,或按 <Esc> | (无需退出) | 浏览、移动光标、执行命令。这是核心模式,大部分时间都在这里。 |
| 插入模式 (Insert) | 按 i, I, a, A, o, O 等 | 按 <Esc> | 输入和编辑文本。就像使用普通文本编辑器一样。 |
| 可视模式 (Visual) | 按 v, V, Ctrl+v | 按 <Esc> | 选择文本块,以便进行后续操作(复制、删除、缩进等)。 |
| 命令行模式 (Ex) | 按 : | 执行后自动退出或按 <Esc> | 执行保存、退出、搜索替换等高级命令。 |
三、常用命令与组合(按场景分类)
以下命令在普通模式下使用(除非指定在命令行模式)。
1. 光标移动 (Navigation) - 脱离方向键
| 命令 | 功能 | 场景 |
|---|---|---|
h, j, k, l | 左,下,上,右 | 基础移动,实现手不离主键盘区 |
w, b | 移动到下一个/上一个单词开头 | 在代码或英文文本中快速跳跃 |
0, $ | 移动到行首/行尾 | 快速定位到行首行尾 |
gg, G | 移动到文件开头/末尾 | 快速浏览长文件 |
[n]G 或 :[n] | 跳转到第 n 行 | 配合编译错误信息快速定位 |
Ctrl+u, Ctrl+d | 向上/向下翻半页 | 快速滚动页面 |
Ctrl+f, Ctrl+b | 向下/向上翻一页 | 快速滚动页面 |
%, ({, }) | 在匹配的括号间跳转 | 检查代码块,快速找到匹配的 {} () [] |
2. 文本编辑 (Editing)
| 命令 | 功能 | 场景 |
|---|---|---|
i, a | 在光标前/后插入 (Insert/Append) | 开始编辑文本 |
I, A | 在行首/行尾插入 | 快速在行首/尾添加内容 |
o, O | 在下方/上方开辟新行 (Open line) | 快速插入新行 |
x, dw, dd | 删除字符/单词/整行 (Delete) | 基础删除操作 |
D | 删除从光标到行尾 | 快速清空行尾 |
r | 替换单个字符 (Replace) | 快速修正拼写错误 |
cw | 修改单词 (Change Word) | 删除一个单词并进入插入模式,高效重命名 |
u, Ctrl+r | 撤销/重做 (Undo/Redo) | 必备操作 |
J | 将下一行连接到当前行尾 (Join) | 合并两行 |
. | 重复上一个编辑操作 | vi 的超级武器,高效执行重复性修改 |
3. 复制、粘贴与选择 (Yank, Put, Visual)
| 命令 | 功能 | 场景 |
|---|---|---|
yw, yy | 复制单词/整行 (Yank) | 复制操作 |
p, P | 在光标后/前粘贴 (Put) | 粘贴操作 |
v | 进入字符可视模式 | 选择任意文本块 |
V | 进入行可视模式 | 按行选择文本 |
Ctrl+v | 进入块可视模式 | 列编辑神器,同时操作多行 |
y, d | (在可视模式下) 复制/删除选中的内容 | 对选中的文本执行操作 |
4. 搜索与替换 (Search & Replace)
| 命令 (模式) | 功能 | 场景 |
|---|---|---|
/pattern | 向前搜索 pattern | 查找内容 |
?pattern | 向后搜索 pattern | 反向查找 |
n, N | 跳转到下一个/上一个匹配项 | 在搜索结果间快速跳转 |
:%s/old/new/g (命令行) | 全局替换 (Substitute) | 将文件中所有 old 替换为 new |
:%s/old/new/gc (命令行) | 全局替换,每次确认 | 安全替换,避免误操作 |
:10,20s/old/new/g (命令行) | 在特定行范围(10-20)内替换 | 精确替换 |
5. 文件与窗口操作 (File & Window)
| 命令 (模式) | 功能 | 场景 |
|---|---|---|
:w | 保存文件 (Write) | 保存当前文件 |
:q | 退出 vi (Quit) | 退出当前窗口 |
:wq 或 ZZ | 保存并退出 | 最常用的退出方式 |
:q! | 不保存强制退出 | 放弃所有修改 |
:e filename | 打开另一个文件 (Edit) | 在不退出vi的情况下编辑新文件 |
:sp [filename] | 水平分割窗口 (Split) | 同时查看或编辑两个文件(上下) |
:vsp [filename] | 垂直分割窗口 (Vertical Split) | 同时查看或编辑两个文件(左右) |
Ctrl+w w | 在窗口间循环切换 | 多窗口编辑时切换焦点 |
:ls | 列出所有缓冲区(打开的文件) | 查看已打开的文件列表 |
:bn, :bp | 切换到下一个/上一个缓冲区 | 在多个打开的文件间切换 |
四、常用组合与实战场景
1. 高效代码编辑
# 组合1:快速注释/取消注释多行代码(块可视模式)
1. 按 `Ctrl+v` 进入块可视模式。
2. 用 `j/k` 选择要注释的行。
3. 按 `I`(大写i),输入注释符(如 `#` 或 `//`)。
4. 按 `<Esc>`,所选所有行首都会自动添加注释符。
# 组合2:快速复制/删除一个函数
1. 将光标移动到函数开始的 `{`。
2. 按 `v%`:进入可视模式并选中到匹配的 `}`。
3. 按 `y` 复制或 `d` 删除。
# 组合3:重命名变量(利用 `*` 搜索和 `cw`)
1. 将光标移到变量名上。
2. 按 `*` 搜索下一个相同的变量。
3. 按 `cw`,输入新变量名,按 `<Esc>`。
4. 按 `n` 找到下一个,按 `.` 重复上一次的修改操作。
2. 系统管理(编辑配置)
# 组合1:快速定位并修改配置
vi +/^PORT /etc/service.conf # 打开文件并直接跳到以PORT开头的行
# 组合2:安全地全局替换(先检查,再替换)
:%s/old_hostname/new_hostname/gc # 每次替换前都会询问确认
# 组合3:同时编辑多个相关配置
vi -O /etc/nginx/nginx.conf /etc/nginx/sites-available/default
# 垂直分屏打开两个配置文件,方便对照修改
3. 日志查看与分析
# 组合1:只读模式查看大日志,防止误触
view /var/log/syslog # 或 vi -R
# 组合2:跳转到日志文件末尾,实时查看新增内容
vi + /var/log/app.log # 打开后,按 `G` 跳转到文件末尾
# 组合3:在日志中搜索特定错误,并高亮显示(vim)
vim +'/ERROR|WARN' +'set hlsearch' /var/log/app.log
# 打开文件,搜索ERROR或WARN,并开启搜索高亮
五、配置优化 (~/.vimrc)
要真正发挥 vim 的威力,需要配置 ~/.vimrc 文件。一些基础设置:
set number " 显示行号
syntax on " 开启语法高亮
set tabstop=4 " Tab键宽度为4空格
set shiftwidth=4 " 自动缩进宽度为4空格
set expandtab " 将Tab转换为空格
set hlsearch " 高亮显示搜索结果
set incsearch " 输入搜索模式时就显示匹配点
set mouse=a " 启用鼠标支持(在支持鼠标的终端中)
总结:vi/vim 哲学
- 模式是核心:大部分时间停留在普通模式,按需短暂进入插入模式,完成后迅速返回
<Esc>。 - 命令可组合:
[次数][命令][范围/文本对象]。例如:d2w(Delete 2 Words):删除 2 个单词。c$(Change to end of line):修改从光标到行尾的内容。5yy(Yank 5 lines):复制 5 行。
.命令是神器:它可以重复任何编辑操作,是自动化简单重复任务的终极武器。
7️⃣awk命令 – 文本分析
awk 是 Linux 中最强大、最灵活的文本处理工具之一,它不仅仅是一个命令,更是一门完整的编程语言,专门设计用于处理结构化文本数据(如日志、CSV、表格数据等)。
它的核心思想是:逐行扫描文件,根据指定的模式匹配条件,执行对应的动作。其基本语法为:
awk 'pattern { action }' input_file
一、核心参数详解与使用场景
| 参数 | 全称/含义 | 使用场景 | 示例 |
|---|---|---|---|
-F fs | --field-separator fs (字段分隔符) | 指定输入文件的字段分隔符。这是最常用的参数,默认为空格和TAB。 | awk -F: '{print $1}' /etc/passwd (用 : 分隔) awk -F'[, ]' '{print $2}' file (使用多个分隔符) |
-v var=value | --assign var=value (变量赋值) | 在 awk 脚本开始执行前,定义一个变量并赋值。用于从外部向 awk 脚本传递参数。 | awk -v name="Alice" '{print name, $1}' file.txt |
-f script-file | --file script-file (文件) | 从脚本文件中读取 awk 命令,而不是在命令行中输入。用于执行复杂、冗长的 awk 脚本。 | awk -f process_data.awk input.txt |
-W option | (GNU awk 扩展选项) | 提供 GNU awk (gawk) 特有的扩展功能。 | awk -W interactive (交互式模式) awk -W version (显示版本) |
二、awk 内置变量与特殊模式
理解这些内置变量是掌握 awk 的关键。
| 变量/模式 | 含义 | 使用场景 |
|---|---|---|
$0 | 当前行的全部内容 | 打印或处理整行 |
$1, $2, ..., $NF | 当前行的第1, 2, …, 最后一个字段 | 处理列数据,NF 是字段总数 |
NF | 当前行的字段数量 (Number of Fields) | print $NF 打印最后一个字段;$(NF-1) 打印倒数第二个 |
NR | 当前处理的行号 (Number of Records) | NR==1 处理第一行(表头);NR>=10 处理10行以后 |
FNR | 当前文件的行号 (File Number of Records) | 处理多个文件时,每个文件的行号独立计数 |
FS | 输入字段分隔符 (Field Separator) | 等同于 -F 参数,可在 BEGIN 块中设置,如 BEGIN{FS=":"} |
OFS | 输出字段分隔符 (Output Field Separator) | 控制 print 输出时各字段间的分隔符,如 BEGIN{OFS="->"} |
RS | 输入记录(行)分隔符 (Record Separator) | 默认为换行符,可修改为其他字符(如处理段落) |
ORS | 输出记录(行)分隔符 (Output Record Separator) | 控制 print 输出时的行结束符,默认为换行符 |
BEGIN{} | 特殊模式,在处理任何输入行之前执行一次 | 初始化变量、打印表头、设置分隔符 |
END{} | 特殊模式,在处理完所有输入行之后执行一次 | 打印汇总信息、计算结果 |
三、常用组合与实战场景
1. 字段提取与打印(最常用场景)
# 1. 打印指定的列(类似 cut 命令)
awk '{print $1, $3}' file.txt # 打印第1和第3列(默认空格分隔)
awk -F, '{print $2 " - " $5}' data.csv # 打印CSV文件的第2和第5列,用" - "连接
# 2. 打印最后一列和倒数第二列
awk '{print $NF, $(NF-1)}' file.txt
# 3. 交换两列的位置
awk '{print $2, $1, $3}' file.txt # 交换第1和第2列
# 4. 格式化输出(类似 printf)
awk '{printf "Name: %-10s Score: %03d\n", $1, $2}' scores.txt
# %-10s: 左对齐,宽度10的字符串
# %03d: 宽度3,不足补0的数字
2. 模式过滤与条件处理(类似 grep + 逻辑判断)
# 1. 打印匹配模式的行(类似 grep)
awk '/error/ {print $0}' system.log # 打印包含 "error" 的行
awk '!/debug/ {print}' app.log # 打印不包含 "debug" 的行({print} 是默认动作,可省略)
# 2. 基于字段值的过滤(这才是awk的威力所在)
awk '$3 > 100 {print $1, $3}' data.txt # 打印第3列值大于100的行的第1和第3列
awk '$1 == "root" {print}' /etc/passwd # 打印第1列为 "root" 的行
awk '$2 ~ /^[0-9]+$/ {print}' file # 打印第2列是数字的行(~ 表示匹配正则)
# 3. 组合条件 (&&, ||, !)
awk '$3 > 50 && $4 == "YES" {print NR, $0}' file # 逻辑与
awk 'NR>=10 && NR<=20 {print}' large_file.txt # 打印10到20行(类似 sed -n)
3. 计算与统计(awk 是计算器)
# 1. 数值计算(对某一列求和、求平均值、找最大值等)
awk '{sum += $3} END {print "Total: ", sum}' data.txt # 对第3列求和
awk '{sum += $3; count++} END {print "Avg: ", sum/count}' data.txt # 求平均值
awk 'max < $3 {max = $3} END {print "Max: ", max}' data.txt # 找最大值
awk 'NR==1 {min=$3} $3 < min {min=$3} END {print "Min: ", min}' data.txt # 找最小值
# 2. 计数(统计出现次数,类似 sort | uniq -c)
awk '{count[$1]++} END {for (ip in count) print ip, count[ip]}' access.log
# 上面是“王牌命令”:统计第一列(假设是IP)的出现次数,用于分析日志来源IP
# 3. 统计不同状态码的出现次数
awk '{status_code=$9; count[status_code]++} END {for (s in count) print s, count[s]}' access.log
4. 文本处理与转换
# 1. 连接多个字段
awk '{print $1 "-" $2 "-" $3}' file.txt
# 或者使用OFS
awk 'BEGIN{OFS="-"} {print $1, $2, $3}' file.txt
# 2. 条件赋值与修改
awk '$3 > 100 {$4 = "High"; print}' data.txt # 如果第3列>100,则设置第4列为"High"并打印
# 3. 处理表头(跳过第一行)
awk 'NR>1 {print $1, $3}' with_header.csv # 不处理标题行
5. 多文件处理与高级用法
# 1. 处理多个文件
awk '{print FILENAME, FNR, $0}' file1.txt file2.txt # 打印内容,并显示文件名和行号
# 2. 使用外部变量(-v 参数)
threshold=50
awk -v thr=$threshold '$3 > thr {print}' data.txt # 使用shell变量$threshold
# 3. 从文件读取脚本(-f 参数)
# 将复杂的awk逻辑写在 script.awk 文件中
# script.awk 内容:
# BEGIN {FS=","; print "Report Start"}
# $3 > 100 {print $1, $3}
# END {print "Report End"}
awk -f script.awk input.csv
四、生产力提升技巧与组合
1. 日志分析经典组合
# 分析Nginx访问日志,统计访问最频繁的10个IP
awk '{ip_count[$1]++} END {for (ip in ip_count) print ip_count[ip], ip}' access.log | sort -nr | head -10
# 统计每个URL的访问次数
awk '{url_count[$7]++} END {for (u in url_count) print url_count[u], u}' access.log | sort -nr
# 计算平均响应大小(假设第10列是响应字节数)
awk '{sum += $10; count++} END {print "Avg Response Size: ", sum/count/1024, "KB"}' access.log
2. 系统监控命令
# 监控当前最耗CPU的进程(结合ps)
ps aux | awk '$3 > 10.0 {print $0}' # 显示CPU使用率超过10%的进程
# 检查磁盘使用率(结合df)
df -h | awk '$5+0 > 80 {print $1, $5}' # 显示使用率超过80%的分区
3. 数据清洗与格式化
# 将CSV文件转换为JSON(简易版)
awk -F, 'BEGIN{print "["} NR>1{printf " {\"name\": \"%s\", \"id\": %s},\n", $1, $2} END{print "]"}' data.csv
# 过滤空白行和注释行
awk 'NF && !/^#/ {print}' config.conf # NF非空(有字段)且不以#开头
五、总结:awk 思维导图
- 选择数据源:文件或管道输入。
- 设置条件 (Pattern):
- 行号:
NR == 1 - 正则:
/error/ - 字段值:
$3 > 100 - 组合:
NR>10 && $2 ~ /pattern/ - 特殊:
BEGIN,END
- 行号:
- 执行动作 (Action):
- 输出:
print,printf - 计算:
sum += $n - 统计:
count[$n]++ - 流程控制:
if (...) {...} else {...},for (key in array) {...}
- 输出:
- 处理结果:输出到屏幕、重定向到文件或通过管道传递给其他命令(如
sort)。
黄金法则:
- 对于基于列的操作、计算和复杂统计,
awk是无可争议的王者。 - 结合
BEGIN和END块,你可以完成从初始化到生成报告的全流程。 awk '{count[$x]++} END {for(i in count)...}'是统计分析万能钥匙,务必掌握。
8️⃣sort命令 - 排序
sort 命令是 Linux 中用于对文本行进行排序的终极工具。它看似简单,但功能异常强大,尤其擅长处理结构化数据(如日志、CSV 文件等),并且是命令行管道中不可或缺的一环。
以下是 sort 命令的参数详解、使用场景和经典组合。
一、核心参数详解与使用场景
1. 排序规则控制(决定如何排序)
| 参数 | 全称/含义 | 使用场景 | 示例 |
|---|---|---|---|
-n | --numeric-sort (数字排序) | 按数值大小而非字符串顺序进行排序。这是最关键的参数之一,避免出现 10 排在 2 前面的情况。 | sort -n file.txt (按数字排) |
-r | --reverse (逆序) | 逆序输出排序结果(默认升序,-r 为降序)。 | sort -nr file.txt (数字降序) |
-f | --ignore-case (忽略大小写) | 排序时忽略字母大小写。将 A 和 a 视为相同。 | sort -f languages.txt |
-u | --unique (去重) | 在排序的同时,去除重复的行。相当于 sort | uniq,但更高效。 | sort -u duplicates.txt |
2. 键定义(指定排序列,核心功能)
| 参数 | 全称/含义 | 使用场景 | 示例 |
|---|---|---|---|
-k, --key=KEYDEF | (指定排序键) | 指定排序所依据的字段(列)范围。KEYDEF 格式为 F[.C][OPTS][,F[.C][OPTS]]。这是 sort 最强大的功能。 | sort -k2,2n data.txt (以第2列为键数字排序) |
-t, --field-separator=SEP | (指定分隔符) | 指定用于分隔字段的字符。默认是空格和TAB。必须与 -k 参数配合使用。 | sort -t',' -k3,3n data.csv (用逗号分隔,按第3列数字排序) |
KEYDEF 格式详解 (-k):
F:字段编号(从1开始)。.C:从该字段的第 C 个字符开始比较(可选,默认为1)。OPTS:一个或多个排序选项(如n,r),覆盖全局选项。,F[.C][OPTS]:指定键的结束位置。如果只指定起始字段,键会延伸到行尾。最佳实践是明确指定起始和结束字段,如-k2,2。
3. 其他实用参数
| 参数 | 全称/含义 | 使用场景 | 示例 |
|---|---|---|---|
-o, --output=FILE | (输出文件) | 将排序结果输出到指定文件。可以安全地用于原地排序(即覆盖原文件),而 sort file > file 会导致文件清空。 | sort -o sorted.txt unsorted.txt |
-c, --check | (检查) | 检查文件是否已排序。如果未排序,则报告错误并退出状态为1。用于脚本中的验证。 | sort -c file.txt && echo "Sorted" || echo "Unsorted" |
-s, --stable | (稳定排序) | 进行稳定排序。保留所有相等输入行的原始顺序。当排序算法不稳定时有用。 | sort -s -k1,1 file |
-h, --human-numeric-sort | (人类可读数字) | 比较人类可读的数字(如 2K, 1G)。用于排序 du -h, ls -lh 的输出。 | du -h | sort -h |
-V, --version-sort | (版本号排序) | 对文本中的版本号进行自然排序。能正确排序 v1.2, v1.10, v2.1。 | sort -V version_list.txt |
-S, --buffer-size=SIZE | (缓冲区大小) | 指定使用的内存大小。用于优化大文件排序性能。 | sort -S 50% file (使用50%内存) sort -S 2G file (使用2GB内存) |
二、常用组合与实战场景
1. 基础排序
# 1. 按字典序(默认)排序
sort names.txt
# 2. 按数字排序(处理纯数字列)
sort -n numbers.txt
# 3. 按数字降序排序
sort -nr numbers.txt
# 4. 排序并去重(非常常用)
sort -u emails.txt
# 等效于
sort emails.txt | uniq
2. 基于列(字段)的排序(处理表格数据)
这是 sort 最强大的功能,用于处理 ls -l, ps, 日志、CSV 等任何结构化输出。
# 1. 按第二列的数字大小进行排序(例如,ps输出的PID列)
ps aux | sort -nk 2
# 2. 按第三列的数字大小进行降序排序(例如,du输出的容量列)
du -sk * | sort -nrk 1
# 注意:因为du -sk输出只有两列,所以第一列就是大小
# 3. 处理CSV文件:按第3列(数字)排序,使用逗号分隔
sort -t',' -k3,3n data.csv
# 4. 指定复杂的多级排序规则
# 先按第2列数字排序(主键),如果相同,再按第1列字典序逆序排序(次键)
sort -k2,2n -k1,1r data.txt
# 5. 处理ls -l的输出:按文件大小(第5列)降序排序
ls -l | sort -nrk 5,5
# 6. 按文件扩展名排序(例如,取最后一个点之后的字符)
ls | sort -t'.' -k2,2
3. 系统监控与性能分析
# 1. 找出最耗内存的10个进程
ps aux | sort -rnk 4 | head -10
# 第4列是 %MEM
# 2. 找出最耗CPU的10个进程
ps aux | sort -rnk 3 | head -10
# 第3列是 %CPU
# 3. 按大小排序当前目录下的文件和目录(人类可读格式)
du -sh * | sort -h
# 这是 -h 参数的经典应用场景
# 4. 查看最大的5个日志文件
find /var/log -name "*.log" -exec du -h {} \; | sort -hr | head -5
4. 数据清洗与预处理
# 1. 检查配置文件是否已按特定键排序(例如,用于后续的join或diff)
sort -c -k1,1 config.txt
# 2. 对两个文件进行排序,为后续比较或合并做准备
sort -o file1.sorted.txt file1.txt
sort -o file2.sorted.txt file2.txt
diff file1.sorted.txt file2.sorted.txt
# 3. 为 `uniq -c` 准备数据(uniq要求输入已排序)
cat words.txt | sort | uniq -c | sort -nr
# 这个组合是“统计词频”的王牌命令:
# 1. sort: 将相同词排在一起
# 2. uniq -c: 计数并去重
# 3. sort -nr: 按计数结果(数字)降序排序,得到最高频的词
5. 高级用法与组合
# 1. 版本号排序(对打包和开发极其有用)
cat versions.txt
# v1.0
# v1.10
# v1.2
# v2.0
sort -V versions.txt # 会正确排序为 v1.0, v1.2, v1.10, v2.0
# 2. 指定特定字符范围作为键(例如,从第3个字符开始比较)
sort -k1.3,1.5 data.txt # 对每行第一个字段的第3到第5个字符进行排序
# 3. 安全地原地排序文件(使用 -o 参数,不要用重定向!)
sort -o large_file.txt large_file.txt # 正确做法
# sort large_file.txt > large_file.txt # 错误做法!会清空文件!
三、sort 与 uniq 的黄金组合
sort 和 uniq 是天生的一对,uniq 依赖于已排序的输入。
| 目标 | 命令组合 | 说明 |
|---|---|---|
| 去重 | sort file | uniq | 基本去重 |
| 显示唯一行 | sort file | uniq -u | 只显示从未重复的行 |
| 显示重复行 | sort file | uniq -d | 只显示重复过的行 |
| 统计出现次数 | sort file | uniq -c | 计数并去重 |
| 统计并排序次数 | sort file | uniq -c | sort -nr | 经典组合:统计频率并排序 |
示例:分析 Web 日志
# 统计访问最频繁的10个IP地址
awk '{print $1}' /var/log/nginx/access.log | sort | uniq -c | sort -nr | head -10
# 统计最受欢迎的10个URL
awk '{print $7}' /var/log/nginx/access.log | sort | uniq -c | sort -nr | head -10
四、总结与最佳实践
- 始终用
-n处理数字:除非你明确希望进行字符串排序(10<2),否则对数字列使用-n。 - 明确指定键范围:使用
-k2,2而不是-k2,避免键意外地延伸到行尾。 - 原地排序用
-o:要对文件自身排序时,永远使用sort -o file file,不要用sort file > file。 - 管道组合是精髓:
sort很少单独使用,它与awk(提取列)、uniq(去重计数)、head/tail(取结果)等命令的组合能解决绝大多数数据分析问题。 - 性能优化:处理超大文件时,使用
-S调整缓冲区大小可以显著提升速度。
决策流程图:

9️⃣uniq命令 - 去重
uniq 命令是 Linux 中用于报告或忽略重复行的实用工具。它通常与 sort 命令结合使用,因为 uniq 的一个关键特性是:它只能检测相邻的重复行。
这意味着输入必须预先排序,才能正确去除所有重复项。
一、核心参数详解与使用场景
| 参数 | 全称/含义 | 使用场景 | 示例 |
|---|---|---|---|
-c | --count (计数) | 在每行前面加上该行重复出现的次数。这是最常用的参数,用于统计频率。 | uniq -c file.txt |
-d | --repeated (重复) | 仅显示重复出现的行(每组重复行只显示一次)。用于快速找出所有重复项。 | uniq -d file.txt |
-u | --unique (唯一) | 仅显示出现一次的行。用于找出所有独一无二的项,过滤掉所有重复项。 | uniq -u file.txt |
-i | --ignore-case (忽略大小写) | 在比较时忽略大小写。将 Hello 和 hello 视为相同的行。 | uniq -i case_sensitive.txt |
-f N | --skip-fields=N (跳过字段) | 跳过每行前面的 N 个字段(由空格/TAB分隔)后再进行比较。用于忽略行首的无关信息(如时间戳、IP)。 | uniq -f 2 log.txt (跳过前2列) |
-s N | --skip-chars=N (跳过字符) | 跳过每行前面的 N 个字符后再进行比较。用于忽略固定的前缀(如行号)。 | uniq -s 5 data.txt (跳过前5个字符) |
-w N | --check-chars=N (检查字符) | 只比较每行前面的 N 个字符。用于只关心行首特定标识符(如用户名、错误码)是否重复的场景。 | uniq -w 3 codes.txt (只比较前3个字符) |
二、常用组合与实战场景
uniq 的强大之处几乎完全体现在与 sort 和其他命令的组合中。
1. 统计分析与计数(最常用场景)
# 1. 统计文件中每行内容的出现次数(经典组合:sort | uniq -c)
sort names.txt | uniq -c
# 输出示例:
# 3 Alice
# 5 Bob
# 2 Charlie
# 2. 按出现频率从高到低排序(另一个经典组合)
sort names.txt | uniq -c | sort -nr
# 输出示例:
# 5 Bob
# 3 Alice
# 2 Charlie
# 3. 找出最常用的10个命令(分析命令行历史)
history | awk '{print $2}' | sort | uniq -c | sort -nr | head -10
2. 数据清洗与去重
# 1. 基本去重(必须先排序!)
sort duplicates.txt | uniq > unique_items.txt
# 2. 直接使用 sort 的 -u 参数(效果等同,更简洁)
sort -u duplicates.txt > unique_items.txt
# 3. 仅找出重复项(例如,找出重复的订单号、用户ID)
sort order_ids.txt | uniq -d
# 4. 仅找出唯一项(例如,找出只出现过一次的异常错误)
sort errors.log | uniq -u
3. 日志分析(结合 -f 参数跳过字段)
日志文件通常带有时间戳、IP等前缀,-f 参数非常有用。
# 假设日志格式: [Timestamp] [LogLevel] Message
# 示例行: [2023-10-27 10:00:01] [ERROR] Database connection failed
# 1. 跳过前2个字段(时间戳和日志级别),只对错误信息本身进行统计
sort app.log | uniq -f 2 -c
# 这会统计每种错误信息出现的次数,而不管它是什么时间发生的
# 2. 分析Nginx访问日志,统计每种HTTP状态码的出现次数
awk '{print $9}' access.log | sort | uniq -c
# $9 是状态码所在的列
# 3. 统计每个IP的访问次数(Web日志分析经典命令)
awk '{print $1}' /var/log/nginx/access.log | sort | uniq -c | sort -nr | head -20
4. 高级文本处理(结合其他命令)
# 1. 比较两个文件(找出只在file1中出现的行)
sort file1.txt file2.txt | uniq -u
# 注意:这实际上会找出两个文件中所有唯一的行。正确做法是:
comm -23 <(sort file1.txt) <(sort file2.txt) # 推荐用 comm 命令
# 2. 忽略大小写进行去重(例如,处理用户输入的标签)
sort -f tags.txt | uniq -i
# 3. 检查代码中重复的函数定义(粗略检查)
grep -r '^def ' /path/to/code/ | sort | uniq -d
三、uniq 与 sort -u 的区别
这是一个常见问题。两者都能去重,但有重要区别:
| 特性 | sort -u | sort | uniq |
|---|---|---|
| 功能 | 排序并去重 | 排序后去重 |
| 输出 | 排序后的唯一行 | 排序后的唯一行 |
| 灵活性 | 较低。只能去重。 | 极高。可与 uniq -c, uniq -d, uniq -u 等参数组合,实现计数、找重复、找唯一等功能。 |
| 性能 | 稍快,一次处理完成 | 稍慢,需要两个命令通过管道连接 |
| 使用场景 | 简单的去重需求 | 复杂的去重和统计分析需求 |
结论:如果只是简单地去重,sort -u 更简洁。如果需要统计次数、仅找重复项或唯一项,必须使用 sort | uniq 组合。
四、注意事项与常见误区
-
输入必须已排序:这是最重要的原则。
uniq无法检测不相邻的重复行。- 错误示范:
uniq unsorted_file.txt(结果不可预测) - 正确做法:
sort file.txt | uniq
- 错误示范:
-
理解“字段”和“字符”:
-f N:跳过由空格/TAB分隔的前 N 个字段。-s N:跳过前 N 个字符(无论是什么)。
-
参数可以组合:例如,
uniq -ic可以同时实现忽略大小写并计数。
五、常用组合速查表
| 场景 | 命令组合 | 说明 |
|---|---|---|
| 统计词频 | sort file | uniq -c | 统计每行出现次数 |
| 按频率排序 | sort file | uniq -c | sort -nr | 王牌组合,列出最高频项 |
| 找出重复项 | sort file | uniq -d | 只显示重复的行 |
| 找出唯一项 | sort file | uniq -u | 只显示不重复的行 |
| 忽略前缀去重 | sort file | uniq -f N | 跳过前N列后比较 |
| 忽略大小写去重 | sort -f file | uniq -i | 将大小写视为相同 |
总结:uniq 本身很简单,但其价值在与其他命令(尤其是 sort)的组合中得以无限放大。掌握 sort | uniq -c | sort -nr 这个统计黄金管道,你就能高效地分析日志、统计数据和进行各种文本挖掘工作。
🔟cut命令 - 裁剪列
cut 命令是 Linux 中一个简单而高效的文本处理工具,它的核心功能是按“列”提取文本内容。它特别擅长处理具有固定分隔符或固定字符位置的规整文本数据。
与功能更强大的 awk 相比,cut 更加轻量和专注,是快速提取字段的利器。
一、核心参数详解与使用场景
cut 主要提供三种方式来定义要提取的“列”。
| 参数 | 全称/含义 | 使用场景 | 示例 |
|---|---|---|---|
-f, --fields=LIST | (字段) | 指定要提取的字段(列),基于分隔符。这是最常用的参数。LIST 可以是单个数字、逗号分隔的列表或范围(如 1,3,5 或 1-3)。 | cut -f1,3 file.txt (提取第1和第3列) |
-d, --delimiter=DELIM | (分隔符) | 指定用于分隔字段的分隔符。默认是TAB字符。必须与 -f 参数配合使用。 | cut -d',' -f2 data.csv (用逗号分隔,提取第2列) |
-c, --characters=LIST | (字符) | 指定要提取的字符位置(按字符数),而不是字段。用于处理固定宽度的文本或从每行特定位置提取数据。 | cut -c1-5,10-15 file.txt (提取1-5和10-15的字符) |
--complement | (补集) | 提取指定字段或字符范围之外的所有内容。相当于“反选”。 | cut -f3 --complement file (提取除第3列外的所有列) |
-s, --only-delimited | (仅分隔行) | 不打印不包含分隔符的行。用于过滤掉那些格式不规范、无法被 -d 和 -f 处理的无效行。 | cut -d':' -f1 -s /etc/passwd (只处理包含冒号的行) |
LIST 格式说明:
N:第 N 个字段/字符(从 1 开始计数)N-:从第 N 个到行尾N-M:从第 N 个到第 M 个(包含)-M:从第 1 个到第 M 个- 组合:
N,M,P或N-M,P-Q
二、常用组合与实战场景
1. 处理基于分隔符的文件(-d 与 -f 组合)
这是 cut 最核心的用途,尤其适用于 CSV、TSV 或类似 /etc/passwd 的系统配置文件。
# 1. 提取 /etc/passwd 文件中的用户名(第1列,冒号分隔)
cut -d':' -f1 /etc/passwd
# 2. 提取 CSV 文件中的第1和第3列
cut -d',' -f1,3 data.csv
# 3. 提取命令输出的特定列(例如,提取 ps 输出的进程ID和命令)
ps aux | cut -d' ' -f1,11- # 注意:空格分隔可能不规整,有局限性
# 更好的方式通常是使用 awk: `ps aux | awk '{print $1, $11}'`
# 4. 提取一个范围列(例如,第2列到最后一列)
cut -d' ' -f2- logfile.txt
# 5. 排除某一列(例如,提取除第2列外的所有列)
cut -d',' -f2 --complement data.csv
2. 处理固定宽度的文本(-c 参数)
适用于处理旧式系统日志、特定格式的输出或固定长度的字符串。
# 1. 提取每行的前10个字符
cut -c1-10 file.txt
# 2. 提取每行的第5到第15个字符
cut -c5-15 file.txt
# 3. 提取单个字符位置(例如,每行的第一个字符)
cut -c1 file.txt
# 4. 结合其他命令(例如,检查文件权限位)
ls -l | cut -c1-10 # 提取类似 '-rwxr-xr-x' 的权限字符串
3. 系统管理与日志分析
# 1. 快速查看磁盘使用率最高的分区(结合 sort 和 head)
df -h | sort -hr -k5 | head -5 | cut -d' ' -f1,5
# 先按使用率排序,再提取分区名和使用率列
# 2. 分析日志,提取时间戳和错误信息(假设时间戳是前15个字符)
cut -c1-15 system.log | sort | uniq -c # 统计每分钟的日志量
# 3. 获取当前主机的IP地址(方法之一)
hostname -I | cut -d' ' -f1 # 第一个IP地址通常是主IP
4. 数据清洗与预处理
# 1. 提取电子邮件地址的用户名部分(@之前)
echo "user@example.com" | cut -d'@' -f1
# 2. 提取文件名的后缀
echo "document.pdf" | cut -d'.' -f2
# 3. 提取文件名的前缀(对于包含多个点的情况可能不准)
echo "archive.tar.gz" | cut -d'.' -f1
# 这种情况下,使用变量扩展或awk更可靠:${filename%%.*}
# 4. 过滤掉文件中的注释(假设注释以#开头,但不在行首无效)
grep -v '^#' config.cfg | cut -d'#' -f1
# 先删除整行注释,再截取行内注释之前的内容
三、cut 的局限性及替代方案
cut 简单高效,但也有明显缺点。了解何时该用 cut,何时该换用其他工具(如 awk)非常重要。
| 场景 | cut 的表现 | 更好的替代方案(通常是 awk) |
|---|---|---|
| 分隔符是空格 | 很差。无法处理连续的空格,会将每个空格都视为分隔符,导致列号错乱。 | awk '{print $1}'。awk 默认会将连续的空格/制表符压缩为一个分隔符。 |
| 字段顺序不固定 | 无法处理。依赖固定的列号。 | awk -F':' '{print $NF}'。可以使用 $NF(最后一列)等相对位置。 |
| 需要格式化输出 | 无法实现。只能简单拼接提取的字段。 | awk -F':' '{printf "User: %-10s UID: %s\n", $1, $3}' /etc/passwd |
| 基于模式提取 | 无法实现。只能按位置提取。 | awk -F':' '$3 > 1000 {print $1}' /etc/passwd (提取普通用户) |
| 重新排列字段顺序 | 可以实现,但很繁琐。cut -f3,1,2 | awk -F',' '{print $3, $1, $2}' OFS=',' data.csv (更直观) |
简单决策指南:
- 数据规整,分隔符是单字符(非空格),只需按位置提取 ->
cut(最快最简) - 数据复杂,分隔符是空格,或需要判断、计算、格式化 ->
awk(功能最强)
四、常用组合速查表
| 场景 | 命令组合 | 说明 |
|---|---|---|
| 提取系统用户名 | cut -d: -f1 /etc/passwd | 经典示例,冒号分隔取第1列 |
| 提取CSV特定列 | cut -d, -f2,4 data.csv | 逗号分隔,取第2和第4列 |
| 提取字符范围 | cut -c1-10 file.txt | 提取每行前10个字符 |
| 排除某一列 | cut -f3 --complement file | 提取除第3列外的所有列 |
| 过滤无效行 | cut -d':' -f1 -s file | 只处理包含分隔符的行 |
| 管道提取 | ps aux | cut -d' ' -f1,11 | 从命令输出中提取列(注意空格问题) |
总结
cut 是一个专注的工具,它的优势在于简单和速度。对于处理结构清晰的文本数据(如 CSV、TSV、/etc/passwd),它是一个无可替代的快速解决方案。
记住它的核心组合:
-d+-f:用于分隔符明确的列。-c:用于固定字符位置的列。
当遇到 cut 无法处理的复杂场景时,不要犹豫,请毫不犹豫地请出它的“老大哥”——awk。
0️⃣tr命令 - 字符替换
好的,tr (translate / transliterate) 是 Linux 中一个简单高效的命令,专门用于对来自标准输入的字符进行替换、压缩和删除。它不像 sed 或 awk 那样功能全面,但正因为其专注,在处理纯字符层面的操作时,它往往更加快捷和简洁。
它的核心语法是:tr [OPTION]... SET1 [SET2]
一、核心参数详解与使用场景
| 参数 | 全称/含义 | 使用场景 | 示例 |
|---|---|---|---|
| (无参,SET1 SET2) | (转换) | 将 SET1 中出现的字符替换为 SET2 中对应位置的字符。这是最基本的功能。 | tr 'abc' 'ABC' (a->A, b->B, c->C) |
-d | --delete (删除) | 删除所有属于 SET1 的字符。 | tr -d '\r' (删除回车符 ^M) |
-s | --squeeze-repeats (压缩重复) | 将 SET1 中列出的重复字符压缩成一个。 | tr -s ' ' (将多个连续空格压缩成一个) |
-c / -C | --complement (补集) | 操作对象是 SET1 的补集(即所有不属于 SET1 的字符)。 | tr -cd '0-9' (删除所有非数字字符) |
预定义字符集 (用于 SET1 或 SET2)
tr 可以理解一些特殊的预定义集合,非常有用。
| 集合 | 含义 | 使用场景 |
|---|---|---|
'[:lower:]' | 所有小写字母 | tr '[:lower:]' '[:upper:]' (小写转大写) |
'[:upper:]' | 所有大写字母 | tr '[:upper:]' '[:lower:]' (大写转小写) |
'[:alpha:]' | 所有字母 (a-z, A-Z) | tr -d '[:alpha:]' (删除所有字母) |
'[:digit:]' | 所有数字 (0-9) | tr -d '[:digit:]' (删除所有数字) |
'[:alnum:]' | 所有字母和数字 | tr -c -d '[:alnum:]' (只保留字母和数字) |
'[:space:]' | 所有空白字符 (空格, TAB, 换行等) | tr -s '[:space:]' (压缩所有空白字符) |
'[:punct:]' | 所有标点符号 | tr -d '[:punct:]' (删除所有标点) |
'[:graph:]' | 所有可打印字符 (不含空格) | |
'[:print:]' | 所有可打印字符 (含空格) | |
'[:cntrl:]' | 所有控制字符 |
二、常用组合与实战场景
1. 字符转换 (最基本的替换)
# 1. 大小写转换 (非常常用)
echo "Hello World" | tr '[:lower:]' '[:upper:]' # 输出: HELLO WORLD
echo "Hello World" | tr 'a-z' 'A-Z' # 等效写法
# 2. 替换特定字符 (例如,将分隔符从空格替换为逗号)
echo "apple banana cherry" | tr ' ' ',' # 输出: apple,banana,cherry
# 3. 替换换行符 (例如,将多行合并为一行,用空格分隔)
cat multi_line.txt | tr '\n' ' ' # 将所有换行符替换为空格
# 注意:这会在最后也加一个空格。更好的工具是 `paste -s` 或 `xargs`。
# 4. 创建简单的加密 (凯撒密码/ROT13)
echo "secret" | tr 'a-zA-Z' 'n-za-mN-ZA-M' # 输出: frperg
echo "frperg" | tr 'a-zA-Z' 'n-za-mN-ZA-M' # 输出: secret (解密)
2. 字符删除 (-d 参数)
# 1. 删除Windows文件中的回车符 (^M) - 经典用法!
# 从Windows拷贝文件到Linux后经常需要执行
cat file_from_win.txt | tr -d '\r' > clean_file.txt
# 或者直接修改文件
tr -d '\r' < file_from_win.txt > clean_file.txt
# 2. 删除所有数字
echo "My phone is 123-4567" | tr -d '[:digit:]' # 输出: My phone is -
# 3. 删除所有标点符号
echo "Hello, World! How's it going?" | tr -d '[:punct:]' # 输出: Hello World Hows it going
# 4. 删除所有非数字字符 (提取纯数字)- 补集 + 删除的强大组合
echo "Phone: (123) 456-7890" | tr -cd '[:digit:]' # 输出: 1234567890
# -c '[:digit:]' 意思是“所有非数字字符”
# -d 意思是“删除”
# 合起来就是“删除所有非数字字符”,效果是只保留数字
3. 字符压缩 (-s 参数)
# 1. 压缩多余的空格 (非常常用,用于清理日志或文本)
echo "This has too many spaces." | tr -s ' ' # 输出: This has too many spaces.
# 2. 压缩空行 (将多个连续换行符压缩成一个)
cat file_with_blanks.txt | tr -s '\n' # 输出内容不变,但空行只剩一行
# 3. 压缩重复字符 (例如,删除重复的字母,虽然实用价值不大,但演示了功能)
echo "boooooooot" | tr -s 'o' # 输出: boot
4. 系统管理与实战组合
tr 经常和其他命令通过管道 (|) 组合,形成强大的单行脚本。
# 1. 生成随机密码 (结合 /dev/urandom)
# 取48字节随机数据,删除所有非字母数字字符,取前16个
head -c 48 /dev/urandom | tr -cd '[:alnum:]' | head -c 16; echo
# 2. 统计文本中不同单词的数量 (tr 处理,sort|uniq 统计)
cat novel.txt | tr -cs '[:alpha:]' '\n' | sort | uniq -c | sort -nr | head -10
# 分解:
# tr -cs '[:alpha:]' '\n':
# -c 补集:非字母字符
# -s 压缩:将连续的匹配压缩成一个
# 整体效果:将所有非字母字符转换为换行符,并压缩多余的换行符。
# 最终效果:每个单词被放在单独的一行。
# sort | uniq -c:排序并计数
# sort -nr:按计数倒序排序
# head -10:显示前10个
# 3. 检查代码中是否包含制表符 (用于强制空格风格的项目)
if cat -A code.py | grep '\^I' > /dev/null; then echo "Contains tabs!"; fi
# 更简单的方法:
if tr -d -c '\t' < code.py | wc -c > 0; then echo "Contains tabs!"; fi
# 分解:删除所有非制表符字符,然后计算剩余字符数。如果大于0,说明有制表符。
# 4. 格式化 ps 输出 (虽然awk更佳,但tr也是一种思路)
ps aux | tr -s ' ' | cut -d ' ' -f 1,2,11
# 先用 tr -s ' ' 压缩连续空格为单个空格,这样 cut 的列号就稳定了。
三、注意事项与局限性
-
不支持正则表达式:
tr只能处理字面字符或字符类,不能使用*,+,.*等正则元字符。这是它与sed的主要区别。tr:echo "hello" | tr 'l*' 'L'(会尝试将l和*都替换成L)sed:echo "hello" | sed 's/l*/L/g'(使用正则,匹配0个或多个l)
-
处理文件:
tr不接受文件名作为参数,它只从标准输入读取。必须使用重定向 (<) 或管道 (|)。- 正确:
tr 'a-z' 'A-Z' < file.txt - 正确:
cat file.txt | tr 'a-z' 'A-Z' - 错误:
tr 'a-z' 'A-Z' file.txt(不会报错,但会忽略 file.txt,等待你从键盘输入)
- 正确:
-
字符集对应:如果
SET1比SET2长,SET2的最后一个字符会被重复使用,以匹配SET1的长度。echo "abc" | tr 'abcde' 'XY'=> 输出XYY。a->X,b->Y,c->Y(最后一个字符Y被复用),d和e也被映射为Y但输入中没有。
-
字符范围:使用范围 like
a-z时要小心,因为它依赖于系统的字符集排序(locale),在某些语言环境下可能不会如你预期的那样工作。
四、总结:高频用法速查表
| 场景 | 命令组合 | 说明 |
|---|---|---|
| 大小写转换 | tr '[:lower:]' '[:upper:]' | 小写转大写 |
| 删除回车符 | tr -d '\r' | 处理Windows文本文件 |
| 压缩空格 | tr -s ' ' | 多个空格变一个 |
| 提取数字 | tr -cd '[:digit:]' | 只保留数字,删除其他一切 |
| 替换分隔符 | tr ' ' '\n' | 空格替换为换行(一行变多行) |
| 删除标点 | tr -d '[:punct:]' | 删除所有标点符号 |
| 生成随机串 | tr -cd '[:alnum:]' < /dev/urandom | head -c 16 | 生成16位随机字母数字密码 |
| 单词分割 | tr -cs '[:alpha:]' '\n' | 将非字母字符全部转换为换行,用于单词统计 |
结论:tr 是一个专注、高效的字符处理工具。对于简单的全局字符替换、删除和压缩任务,它是首选,速度往往比 sed 更快。对于涉及模式匹配(正则表达式)或更复杂逻辑的任务,则需要使用 sed 或 awk。掌握 tr 能让你的命令行文本处理技巧更加精炼和高效。
1️⃣wc命令 - 计数
wc (word count) 命令是 Linux 中一个简单但极其实用的工具,用于统计文件或输入流中的行数、单词数和字节数。它是系统管理、日志分析和编程工作中进行快速统计的利器。
以下是 wc 命令的参数详解、使用场景和经典组合。
一、核心参数详解与使用场景
wc 的参数非常直观,每个参数对应一种统计维度。
| 参数 | 全称/含义 | 使用场景 | 示例 |
|---|---|---|---|
-l | --lines (行数) | 统计行数。这是最常用的参数,用于统计代码行数、日志条目数、文件数量等。 | wc -l file.txt |
-w | --words (单词数) | 统计单词数(以空格、TAB、换行符分隔的字符串)。用于粗略评估文档长度。 | wc -w essay.txt |
-c | --bytes (字节数) | 统计字节数。用于查看文件的确切大小(与 ls -l 看到的相同)。 | wc -c image.jpg |
-m | --chars (字符数) | 统计字符数。对于 ASCII 文本,与 -c 相同;对于 Unicode 文本(如中文),一个字符可能占多个字节。 | `echo “你好” |
| (无参数) | 同时显示行数、单词数、字节数和文件名。提供所有基本信息。 | wc report.txt |
输出格式说明:
无论使用哪个参数,输出格式通常为:
行数 单词数 字节数 文件名
如果从标准输入读取数据,则不显示文件名。
二、常用组合与实战场景
wc 的真正威力在于与其他命令通过管道 (|) 组合,形成强大的统计单行脚本。
1. 代码与文档统计(最经典场景)
# 1. 统计一个源代码文件的总行数
wc -l main.c
# 2. 统计当前目录下所有 .py 文件的总行数(递归)
find . -name "*.py" -exec cat {} \; | wc -l
# 或者更高效的方法(避免启动多个cat进程):
find . -name "*.py" -print0 | xargs -0 wc -l
# 3. 分别统计每个 .py 文件的行数,并显示总计
wc -l *.py
# 4. 统计当前项目的总代码行数(只统计源代码,排除空行和注释)
find . -name "*.py" -exec cat {} \; | grep -v '^\s*$' | grep -v '^\s*#' | wc -l
# 分解:
# grep -v '^\s*$':排除空行和只有空白字符的行
# grep -v '^\s*#':排除以 # 开头的注释行(Python)
2. 系统管理与日志分析
# 1. 统计当前目录下的文件和目录总数(不包括隐藏文件)
ls -l | wc -l
# 注意:ls -l 的第一行是"总计"行,所以实际数量是 (wc -l 的结果 - 1)
# 2. 更准确的方法:使用 find
find . -maxdepth 1 -type f | wc -l # 只统计文件
find . -maxdepth 1 -type d | wc -l # 只统计目录(包括当前目录.)
# 3. 统计日志文件中的错误条目数
grep -i "error" /var/log/syslog | wc -l
# 4. 监控日志增长速度(每秒打印一次行数变化)
watch -n 1 'tail -n 100 app.log | wc -l'
3. 数据验证与处理
# 1. 比较两个文件的大小是否相同
if [ $(wc -c < file1.txt) -eq $(wc -c < file2.txt) ]; then
echo "Files are the same size"
fi
# 2. 检查一个文件是否为空(行数为0)
if [ $(wc -l < config.cfg) -eq 0 ]; then
echo "Config file is empty!"
fi
# 3. 计算文件的平均单词长度(awk辅助计算)
wc -ww file.txt | awk '{print $2 / $1}'
4. 创作与写作
# 1. 统计文章的总单词数(英文写作常用)
wc -w novel.txt
# 2. 统计Markdown文档的字符数(中英文混合)
wc -m README.md
# 3. 实时统计输入的字数(按Ctrl+D结束输入)
wc -w
# 然后开始输入内容,完成后按 Ctrl+D
三、重要注意事项与技巧
-
-c与-m的区别:-c(bytes):文件在磁盘上占用的实际字节数。对于包含中文等非ASCII字符的UTF-8文本,一个字符可能占用2-4个字节。-m(chars):文本中包含的字符数量。一个中文字符算一个。- 示例:一个包含
你好两个字符和一個换行符的文本文件。echo "你好" > test.txt wc -c test.txt # 可能输出 7 (UTF-8编码中,每个中文3字节,加上换行符1字节:3+3+1=7) wc -m test.txt # 输出 3 (2个字符 + 1个换行符)
-
从标准输入读取:使用
<重定向或管道|时,wc不会输出文件名。wc -l < /etc/passwd # 只输出一个数字:文件行数 cat /etc/passwd | wc -l # 同上,但多创建一个进程,效率较低 -
处理大量文件:使用
xargs避免 “Argument list too long” 错误。# 错误:文件太多时可能出错 wc -l *.log # 正确:使用 find + xargs find . -name "*.log" -print0 | xargs -0 wc -l -
统计文件数量:虽然
wc -l常用于统计ls或find输出的行数来间接统计文件数,但有更可靠的工具:# 统计当前目录下的文件数(不包括隐藏文件和目录本身) find . -maxdepth 1 -type f | wc -l # 使用 awk 统计 ls -l 的有效行(更准确) ls -l | awk '/^-/{count++} END {print count}'
四、常用组合速查表
| 场景 | 命令组合 | 说明 |
|---|---|---|
| 统计代码行数 | find . -name "*.c" -exec cat {} \; | wc -l | 统计所有C文件总行数 |
| 统计错误日志数 | grep "ERROR" app.log | wc -l | 统计错误出现的次数 |
| 查看文件大小 | wc -c < file.iso | 查看文件的字节大小 |
| 统计单词数 | wc -w essay.txt | 统计文档中的单词数 |
| 统计目录文件数 | ls -l | wc -l | 粗略统计(行数-1) |
| 统计字符数 | wc -m document.txt | 统计字符数(适用于中文) |
| 统计每文件行数 | wc -l *.py | 统计每个Python文件的行数并显示总计 |
总结
wc 是一个专注、高效的统计工具。它的核心价值在于其简洁和可组合性。
- 记住三个核心参数:
-l(行数),-w(单词数),-c(字节数)。 - 理解其定位:
wc本身不筛选数据,它总是依赖于find,grep,ls等命令来提供需要统计的输入流。 - 掌握王牌组合:
find | xargs wc -l:统计大量文件的行数。grep | wc -l:统计匹配模式的出现次数。ls | wc -l:粗略统计文件数量。
969

被折叠的 条评论
为什么被折叠?



