Shell脚本实用技巧:正则表达式与文本处理
AWK命令基础应用
AWK是一种强大的文本处理工具,特别适合处理结构化数据。以下是一些基本用法:
# 使用逗号作为分隔符,输出第一列和第二列
awk -F',' '{print $1, $2}' data.txt
# 输出所有行
awk '{print $0}' data.txt
# 根据条件筛选行
awk '$3 > 100 {print $1, $2}' data.txt
正则表达式:grep与sed
grep和sed是Linux中处理文本的强大工具,结合正则表达式可以实现复杂的文本匹配和替换操作。
sed命令详解
sed(Stream Editor)是一个流编辑器,可以对文本进行增、删、改、查操作。
基本语法
sed [选项] [动作] [文件]
常用选项
- -n:安静模式,仅显示处理过的行
- -e:执行多条命令
- -f:从文件中读取脚本
- -i:直接编辑文件(注意备份)
常用动作
- a\:在当前行下面插入文本
- i\:在当前行上面插入文本
- c\:替换选定行为新文本
- d:删除选定行
- s:替换指定字符
- p:打印行(通常与-n一起使用)
- g:行内全局替换
sed元字符
| 元字符 | 说明 | 示例 |
|---|---|---|
| ^ | 匹配行首 | /^test/ 匹配所有以test开头的行 |
| $ | 匹配行尾 | /test$/ 匹配所有以test结尾的行 |
| . | 匹配任意字符(除换行符) | /t.st/ 匹配t后接任意字符,最后是st |
| * | 匹配0个或多个字符 | /*test/ 匹配0个或多个空格后紧跟test的行 |
| [] | 匹配指定范围内的字符 | /[tx]est/ 匹配test和xest |
文本操作示例
插入文本
# 在第2行后插入文本
sed '2a\新插入的文本' filename.txt
# 在匹配"keyword"的行前插入文本
sed '/^keyword/i\插入的文本' filename.txt
删除行
# 删除第3行
sed '3d' filename.txt
# 删除第2至5行
sed '2,5d' filename.txt
# 删除所有包含"keyword"的行
sed '/keyword/d' filename.txt
# 删除空白行
sed '/^$/d' filename.txt
替换文本
# 全局替换"old"为"new"
sed 's/old/new/g' filename.txt
# 替换每行第2处匹配的"old"为"new"
sed 's/old/new/2g' filename.txt
# 仅打印发生替换的行
sed -n 's/old/new/p' filename.txt
高级匹配技巧
# 使用&引用匹配的文本
echo "hello world" | sed 's/\w\+/(&)/g'
# 输出: (hello) (world)
# 使用子串匹配标记
echo "ID=12345" | sed 's/ID=\([0-9]\+\)/编号:\1/'
# 输出: 编号:12345
文件内容管理
创建或替换文件内容
# 创建新文件或替换整个文件内容
cat << EOF > /etc/motd
#####################################
# 系统名称: 服务器管理系统
# 管理员A: admin@example.com
# 管理员B: backup@example.com
# 系统用途: 生产环境Web服务
#####################################
EOF
追加内容到文件
# 追加多行内容到文件末尾
cat << EOF >> /etc/motd
系统维护时间: 每周六凌晨2:00-4:00
紧急联系人: 13800138000
EOF
在文件特定位置插入内容
# 在文件末尾添加内容
sed -i '$a新增的配置行' /etc/config.conf
# 在第N行插入内容
sed -i '5i\插入的配置项' /etc/config.conf
# 替换匹配的行内容
sed -i '/旧配置/c\新配置内容' /etc/config.conf
组合使用grep、sed和awk
查找并替换特定内容
# 查找包含特定模式的行并替换
grep -n "pattern" file.txt | while read line; do
line_num=$(echo $line | cut -d: -f1)
sed -i "${line_num}s/pattern/replacement/g" file.txt
done
提取并处理特定字段
# 提取特定列的值
column_value=$(grep "pattern" file.txt | awk '{print $4}')
# 使用分隔符提取子字段
sub_field=$(echo $column_value | cut -d"=" -f2)
# 根据条件处理数据
grep "condition" data.txt | awk -F: '{if ($3 > 100) print $1, $2}'
处理系统配置文件
# 查找并修改配置值
config_value=$(grep "CONFIG_ITEM" /etc/system.conf | cut -d"=" -f2)
if [ -n "$config_value" ]; then
line_num=$(grep -n "CONFIG_ITEM" /etc/system.conf | cut -d: -f1)
sed -i "${line_num}s/.*/CONFIG_ITEM=new_value/" /etc/system.conf
fi
AWK高级应用
处理/etc/passwd文件
# 查找具有root权限的账号(GID为0)
awk -F: '{if ($4 == 0) print NR, $0}' /etc/passwd
# 跳过首行,显示用户ID和行号
awk -F: 'NR > 1 {print NR, $3}' /etc/passwd
# 统计每个shell的使用情况
awk -F: '{shell[$7]++} END {for (sh in shell) print sh, shell[sh]}' /etc/passwd
数据格式转换
# CSV数据处理
awk -F, '{print "用户名: " $1 ", 年龄: " $2 ", 城市: " $3}' users.csv
# 计算数值列的总和
awk -F, '{sum += $3} END {print "总和: " sum}' data.csv
# 按列排序
awk -F, '{print $2, $1}' names.csv | sort
系统管理实用技巧
文件备份与时间戳
# 添加时间戳备份文件
mv /etc/config.conf /etc/config.conf.backup.$(date +%Y%m%d_%H%M%S)
# 批量备份多个文件
for file in /etc/*.conf; do
mv "$file" "$file.backup.$(date +%Y%m%d)"
done
日志处理
# 提取特定时间段的日志
sed -n '/2023-06-01 10:00/,/2023-06-01 11:00/p' system.log
# 统计错误日志数量
grep "ERROR" application.log | wc -l
# 查找访问量最高的IP
awk '{ip[$1]++} END {for (addr in ip) print ip[addr], addr}' access.log | sort -nr | head -10