Shell文本处理与重定向
Shell文本处理与重定向
十七、文本处理工具
17.1 cut 剪切
cut命令用于截取文件中指定的列或字符。
参数:
-f:指定要提取的列号(field)-d:指定字段分隔符(delimiter)-c:截取指定位置的字符(character)-b:截取指定位置的字节(byte)
示例:
# 假设有文件 data.txt 内容如下:# name age city# John 25 NewYork# Alice 30 London# 提取第一列cut-d' '-f1data.txt# name# John# Alice# 提取第一列和第三列cut-d' '-f1,3data.txt# name city# John NewYork# Alice London# 提取第一列到第三列cut-d' '-f1-3 data.txt# 提取前5个字符cut-c1-5 data.txt# 提取第5-7个字符cut-c5-7 data.txt实用案例:提取 CSV 文件中的特定列
# 提取 CSV 文件的第2列和第4列cut-d','-f2,4users.csv17.2 sed 流编辑器
sed是一个流编辑器,用于对文本进行查找、替换、插入、删除等操作。它一次处理一行内容。
参数:
-e:指定多个编辑命令-n:静默模式,只显示匹配的行-i:直接修改文件内容(in-place)
常用命令:
a:在指定行后追加内容d:删除指定行s:替换内容p:打印指定行
示例:
# 在第3行后追加内容sed'3a New Line'file.txt# 删除第1行sed'1d'file.txt# 删除包含 "pattern" 的行sed'/pattern/d'file.txt# 删除第1-3行sed'1,3d'file.txt# 替换第一个匹配sed's/old/new/'file.txt# 替换所有匹配(全局替换)sed's/old/new/g'file.txt# 只打印第5行sed-n'5p'file.txt# 打印第1-5行sed-n'1,5p'file.txt# 多个命令组合sed-e'1d'-e's/old/new/g'file.txt# 直接修改文件(谨慎使用)sed-i's/old/new/g'file.txt特殊模式:
# 删除空行sed'/^$/d'file.txt# 从第3行开始到第一个空行结束sed'3,/^$/!d'file.txt# 删除选中之外的内容(只保留选中内容)sed'3,/^$/!d'file.txt|sed'/^$/d'17.3 awk 文本分析
awk是一个强大的文本分析工具,以行为单位处理数据,支持条件判断和计算。
参数:
-F:指定字段分隔符-v:定义变量
基本用法:
# 打印指定列awk'{print $1, $3}'data.txt# 指定分隔符awk-F',''{print $1, $2}'users.csv# 打印行号和内容awk'{print NR, $0}'file.txt# 条件筛选awk'$2 > 30'data.txt# 第二列大于30的行# 条件判断awk'{if($2 > 30) print $1, "is old"; else print $1, "is young"}'data.txt# 计算求和awk'{sum += $2} END {print "Total:", sum}'data.txt# 求平均值awk'{sum += $2; count++} END {print "Average:", sum/count}'data.txtBEGIN 和 END 块:
# BEGIN 在处理数据前执行awk'BEGIN {print "Name\tAge"} {print $1"\t"$2}'data.txt# END 在处理数据后执行awk'{sum += $2} END {print "Total Age:", sum}'data.txt# 同时使用 BEGIN 和 ENDawk'BEGIN {print "Processing..."} {print $0} END {print "Done"}'data.txt示例:处理员工数据
# 假设 employees.txt 内容:# Alice,28,5000# Bob,35,7000# Charlie,42,9000# 提取工资大于6000的员工awk-F',''$3 > 6000'employees.txt# 计算平均工资awk-F',''{sum += $3; count++} END {print "Average:", sum/count}'employees.txt17.4 grep 过滤
grep是一个强大的文本搜索工具,用于查找匹配的字符串。
参数:
-v:反向匹配(排除)-c:统计匹配行数-n:显示行号-i:忽略大小写-E:支持扩展正则表达式-r:递归搜索目录
基本用法:
# 查找包含 "pattern" 的行grep"pattern"file.txt# 忽略大小写grep-i"pattern"file.txt# 显示行号grep-n"pattern"file.txt# 统计匹配行数grep-c"pattern"file.txt# 反向匹配(排除)grep-v"pattern"file.txt# 递归搜索目录grep-r"pattern"/path/to/directory# 显示匹配内容及其上下文(前后各2行)grep-C2"pattern"file.txt正则表达式:
# 查找以 "start" 开头的行grep"^start"file.txt# 查找以 "end" 结尾的行grep"end$"file.txt# 查找包含数字的行grep"[0-9]"file.txt# 查找以字母开头的行grep"^[a-zA-Z]"file.txt# 多条件匹配(使用扩展正则)grep-E"pattern1|pattern2"file.txt# 查找包含 "error" 或 "warning" 的行grep-E"error|warning"log.txt实用案例:
# 查看特定进程ps-ef|grepsshd# 排除 grep 自身ps-ef|grepsshd|grep-vgrep# 在多个文件中搜索grep"TODO"*.sh# 统计代码文件中的注释行数grep-c"^//"*.java十八、输入输出重定向
18.1 输出重定向
输出重定向用于将命令的输出保存到文件或设备。
符号说明:
| 符号 | 说明 |
|---|---|
> | 覆盖输出(创建或覆盖文件) |
>> | 追加输出(添加到文件末尾) |
2> | 错误输出重定向 |
&> | 标准输出和错误输出合并重定向 |
示例:
# 将命令输出写入文件(覆盖)ls-l>file_list.txt# 将命令输出追加到文件echo"New entry">>log.txt# 将错误输出写入文件lsnonexistent_file2>error.log# 将标准输出和错误输出都写入文件command&>output.log# 将标准输出和错误输出分开保存command>output.log2>error.log# 将错误输出重定向到标准输出command2>&1# 丢弃输出(黑洞)command>/dev/nullcommand&>/dev/null18.2 输入重定向
输入重定向用于从文件读取输入。
符号说明:
| 符号 | 说明 |
|---|---|
< | 从文件读取输入 |
<< | Here-document(内联输入) |
示例:
# 从文件读取输入wc-l<file.txt# Here-document(创建文件内容)cat>newfile.txt<<EOF This is line 1 This is line 2 This is line 3 EOF# Here-stringgrep"pattern"<<<"This is a test string"18.3 重定向组合使用
# 将多个命令的输出合并到一个文件ls-l>output.txtecho"---">>output.txtdate>>output.txt# 管道和重定向组合ls-l|grep.txt>txt_files.txt# 错误输出和标准输出分别处理command>success.log2>error.log# 将错误输出追加到日志command2>>error.log十九、管道
管道用于将一个命令的输出作为另一个命令的输入。
符号:|
基本用法:
# 连接两个命令command1|command2# 连接多个命令command1|command2|command3示例:
# 列出文件并统计数量ls-l|wc-l# 查找包含特定内容的文件ls-l|grep.txt# 过滤并排序ls-l|grep.txt|sort# 统计日志中错误出现的次数catlog.txt|grep-c"ERROR"# 查找最大的文件ls-la|sort-k5-r|head-n5# 统计文件类型分布ls-l|awk'{print $1}'|cut-c1|sort|uniq-c实用案例:
# 查看磁盘使用情况并按大小排序df-h|sort-k5-h# 查找占用内存最多的进程psaux|sort-k4-r|head-n10# 统计访问日志中最频繁的 IPcataccess.log|awk'{print $1}'|sort|uniq-c|sort-r|head-n10# 从压缩文件中搜索内容zcat logs.gz|grep"ERROR"# 格式化输出ls-l|awk'{printf "%-20s %5s\n", $9, $5}'二十、综合示例
20.1 日志分析脚本
#!/bin/bash# 分析日志文件LOG_FILE="/var/log/syslog"echo"=== 日志分析报告 ==="echo""# 统计错误数量echo"1. 错误数量:"grep-c"ERROR"$LOG_FILE# 显示最近的10条错误echo""echo"2. 最近10条错误:"grep"ERROR"$LOG_FILE|tail-n10# 统计各等级日志数量echo""echo"3. 日志等级分布:"grep-E"(ERROR|WARNING|INFO)"$LOG_FILE|awk'{print $5}'|sort|uniq-c# 查找最频繁出现的错误echo""echo"4. 最频繁的错误:"grep"ERROR"$LOG_FILE|awk'{print $6}'|sort|uniq-c|sort-r|head-n520.2 文件备份脚本
#!/bin/bash# 备份指定目录SOURCE_DIR="/home/user/documents"BACKUP_DIR="/backup"TIMESTAMP=$(date+%Y%m%d_%H%M%S)BACKUP_FILE="backup_$TIMESTAMP.tar.gz"echo"开始备份..."# 创建备份目录mkdir-p$BACKUP_DIR# 执行备份tar-zcvf"$BACKUP_DIR/$BACKUP_FILE"$SOURCE_DIRif[$?-eq0];thenecho"备份成功:$BACKUP_FILE"echo"备份大小:$(du-h"$BACKUP_DIR/$BACKUP_FILE"|awk'{print $1}')"elseecho"备份失败!"exit1fi# 保留最近7天的备份echo"清理旧备份..."find$BACKUP_DIR-name"backup_*.tar.gz"-mtime+7-deleteecho"完成!"20.3 批量文件重命名
#!/bin/bash# 将所有 .txt 文件重命名为 .bakforfilein*.txt;domv"$file""${file%.txt}.bak"done# 添加前缀forfilein*.jpg;domv"$file""photo_$file"done# 数字编号count=1forfilein*.png;domv"$file""image_$(printf"%03d"$count).png"count=$[$count+1]done20.4 系统监控脚本
#!/bin/bashecho"=== 系统状态报告 ==="echo""# CPU 使用情况echo"CPU 使用:"top-bn1|grep"Cpu(s)"|sed"s/.*, *\([0-9.]*\)%* id.*/\1/"|awk'{print "空闲: " 100 - $1 "%"}'# 内存使用情况echo""echo"内存使用:"free-h|grepMem|awk'{print "总计: " $2 ", 已用: " $3 ", 空闲: " $4}'# 磁盘使用情况echo""echo"磁盘使用:"df-h/|grep/|awk'{print "总计: " $2 ", 已用: " $3 ", 可用: " $4 ", 使用率: " $5}'# 运行时间echo""echo"系统运行时间:"uptime|awk'{print "已运行: " $3 " " $4}'# 活跃用户echo""echo"活跃用户:"who|wc-l