Skip to content

7. 文本处理

7.1 grep — 文本搜索

bash
# 基本搜索
grep "error" /var/log/syslog

# 忽略大小写
grep -i "error" /var/log/syslog

# 显示行号
grep -n "TODO" script.py

# 递归搜索目录
grep -r "password" /etc/ --include="*.conf"

# 反向匹配(排除)
grep -v "^#" /etc/nginx/nginx.conf

# 显示匹配行的上下文(前后各3行)
grep -C 3 "panic" /var/log/kern.log

# 使用正则表达式
grep -E "error|warning|critical" /var/log/syslog

# 统计匹配行数
grep -c "error" /var/log/syslog
bash
$ grep -n "error" /var/log/syslog
42:Jun 20 09:15:23 server kernel: [ERROR] USB device not responding
107:Jun 20 09:30:45 server sshd[1234]: error: PAM: Authentication failure
256:Jun 20 10:05:12 server nginx: [error] connect() failed (111: Connection refused)

$ grep -c "error" /var/log/syslog
3

7.2 sed — 流编辑器

bash
# 替换文本(仅显示,不修改文件)
echo "Hello World" | sed 's/World/Linux/'

# 替换并写入文件(-i 直接修改)
sed -i 's/old/new/g' config.txt

# 替换前先备份(-i.bak)
sed -i.bak 's/127.0.0.1/0.0.0.0/g' /etc/mysql/my.cnf

# 删除空行
sed '/^$/d' file.txt

# 删除包含某模式的行
sed '/pattern/d' file.txt

# 只打印第 5-10 行
sed -n '5,10p' file.txt

# 在第 3 行前插入内容
sed '3i\新增的一行内容' file.txt

# 在第 3 行后追加内容
sed '3a\新增的一行内容' file.txt
bash
$ echo "Hello World" | sed 's/World/Linux/'
Hello Linux

$ cat config.txt
server_name example.com
listen 80
root /var/www/html

$ sed 's/listen 80/listen 8080/g' config.txt
server_name example.com
listen 8080
root /var/www/html

7.3 awk — 文本分析利器

bash
# 按列提取(默认以空白分隔)
awk '{print $1, $3}' file.txt

# 指定分隔符
awk -F: '{print $1, $7}' /etc/passwd

# 条件过滤
awk -F: '$3 >= 1000 {print $1}' /etc/passwd

# 计算总和
ls -l | awk 'NR>1 {sum+=$5} END {print "Total:", sum}'

# 格式化输出
df -h | awk '{printf "%-20s %s\n", $1, $5}'
bash
$ awk -F: '$3 >= 1000 {print $1, $7}' /etc/passwd
nobody /usr/sbin/nologin
user /bin/bash
john /bin/bash
jane /bin/bash

$ df -h | awk '{printf "%-20s %s\n", $1, $5}'
Filesystem           Use%
/dev/sda1            45%
tmpfs                1%
/dev/sda2            78%

7.4 其他文本工具

bash
# cut — 按列提取(适合 CSV)
cut -d: -f1,3 /etc/passwd

# sort — 排序
sort /etc/passwd             # 字母排序
sort -t: -k3 -n /etc/passwd  # 按第3列数值排序
sort -u file.txt             # 排序并去重

# uniq — 去重(需先排序)
sort file.txt | uniq
sort file.txt | uniq -c      # 统计重复次数

# wc — 统计
wc -l /etc/passwd            # 行数
wc -w file.txt               # 字数
wc -c file.txt               # 字节数

# tr — 字符替换/删除
echo "Hello World" | tr 'a-z' 'A-Z'    # 转大写
echo "Hello   World" | tr -s ' '       # 压缩空格
echo "abc123" | tr -d '0-9'             # 删除数字

# tee — 既输出到屏幕又写入文件
ls -l | tee file_list.txt
bash
$ sort /etc/passwd | uniq -c | sort -rn | head -5
      1 nobody:x:65534:65534:nobody:/nonexistent:/usr/sbin/nologin
      1 root:x:0:0:root:/root:/bin/bash
      1 sys:x:3:3:sys:/dev:/usr/sbin/nologin

$ wc -l /etc/passwd
35 /etc/passwd

$ echo "Hello World" | tr 'a-z' 'A-Z'
HELLO WORLD

7.5 管道与重定向

管道(|):将一个命令的输出作为下一个命令的输入,就像工厂的流水线。

bash
# 管道链示例:统计 /etc/passwd 中有多少个可登录用户
grep -v "nologin\|false" /etc/passwd | wc -l

# 查找占用空间最大的前5个目录
du -sh /home/* 2>/dev/null | sort -rh | head -5

# 查看最消耗内存的前5个进程
ps aux --sort=-%mem | head -6

# 重定向:输出到文件(覆盖)
echo "Hello" > output.txt

# 重定向:追加到文件
echo "World" >> output.txt

# 错误重定向
find / -name "*.conf" 2> /dev/null

# 同时重定向标准输出和错误
command &> all_output.txt

# Here Document(多行输入)
cat << EOF
server {
    listen 80;
    server_name example.com;
}
EOF
bash
$ grep -v "nologin\|false" /etc/passwd | wc -l
4

$ du -sh /home/* 2>/dev/null | sort -rh | head -5
2.1G	/home/user
850M	/home/john
320M	/home/jane
50M	/home/www

$ ps aux --sort=-%mem | head -6
USER       PID %CPU %MEM    VSZ   RSS TTY      STAT START   TIME COMMAND
mysql     1234  2.3 12.5 1843652 512340 ?      Sl   Jun19  10:30 /usr/sbin/mysqld
www-data  2345  0.5  8.2 856432 335876 ?       S    Jun19   2:15 apache2 -k start
root       567  0.1  3.1 225432 127844 ?       Ss   Jun19   0:45 /usr/bin/dockerd
user      3456  1.2  2.8 987654 115234 pts/0   S+   10:00   0:15 vim largefile.txt
符号含义示例
>标准输出重定向(覆盖)echo hi > f.txt
>>标准输出重定向(追加)echo hi >> f.txt
2>标准错误重定向cmd 2> err.log
&>全部输出重定向cmd &> all.log
<<标准输入重定向wc -l < file.txt
|管道(传递输出)ls | grep txt