文本处理是Linux系统管理的重要技能,通过grep、sed、awk等工具,可以高效地搜索、过滤、转换和处理文本数据。本章将详细介绍这些强大的文本处理工具。
常用元字符:
| 元字符 | 说明 | 示例 |
|---|---|---|
. |
匹配任意单个字符 | a.c 匹配 abc、adc、a1c |
* |
匹配前一个字符0次或多次 | ab*c 匹配 ac、abc、abbc |
^ |
匹配行首 | ^root 匹配以root开头的行 |
$ |
匹配行尾 | bash$ 匹配以bash结尾的行 |
[] |
匹配字符集合 | [abc] 匹配a或b或c |
[^] |
匹配不在集合中的字符 | [^0-9] 匹配非数字字符 |
\ |
转义字符 | \. 匹配点号本身 |
\< |
匹配单词开头 | \<root 匹配以root开头的单词 |
\> |
匹配单词结尾 | bash\> 匹配以bash结尾的单词 |
示例:
# 匹配以root开头的行
grep '^root' /etc/passwd
# 匹配以bash结尾的行
grep 'bash$' /etc/passwd
# 匹配空行
grep '^$' /etc/passwd
# 匹配包含数字的行
grep '[0-9]' /etc/passwd
# 匹配不包含数字的行
grep '[^0-9]' /etc/passwd
# 匹配邮箱格式
grep '[a-zA-Z0-9._%+-]*@[a-zA-Z0-9.-]*\.[a-zA-Z]*' file.txt
东巴文理解:正则表达式是文本处理的基石,掌握元字符是关键。
预定义字符类:
| 字符类 | 说明 | 等价于 |
|---|---|---|
[:alnum:] |
字母和数字 | [a-zA-Z0-9] |
[:alpha:] |
字母 | [a-zA-Z] |
[:digit:] |
数字 | [0-9] |
[:lower:] |
小写字母 | [a-z] |
[:upper:] |
大写字母 | [A-Z] |
[:space:] |
空白字符 | [ \t\n\r\f\v] |
[:punct:] |
标点符号 | [!"#$%&'()*+,-./:;<=>?@[\]^_\{|}~]` |
示例:
# 匹配数字
grep '[[:digit:]]' /etc/passwd
# 匹配字母
grep '[[:alpha:]]' /etc/passwd
# 匹配小写字母
grep '[[:lower:]]' /etc/passwd
# 匹配空白字符
grep '[[:space:]]' /etc/passwd
扩展正则表达式元字符:
| 元字符 | 说明 | 示例 |
|---|---|---|
+ |
匹配前一个字符1次或多次 | ab+c 匹配 abc、abbc、abbbc |
? |
匹配前一个字符0次或1次 | ab?c 匹配 ac、abc |
| ` | ` | 或运算符 |
() |
分组 | (ab)+ 匹配 ab、abab、ababab |
{n} |
匹配前一个字符n次 | a{3} 匹配 aaa |
{n,} |
匹配前一个字符至少n次 | a{3,} 匹配 aaa、aaaa、aaaaa |
{n,m} |
匹配前一个字符n到m次 | a{2,4} 匹配 aa、aaa、aaaa |
示例:
# 使用扩展正则表达式(-E选项)
grep -E 'ab+c' file.txt # 匹配 abc、abbc、abbbc
grep -E 'ab?c' file.txt # 匹配 ac、abc
grep -E 'a|b' file.txt # 匹配 a 或 b
grep -E '(ab)+' file.txt # 匹配 ab、abab、ababab
grep -E 'a{3}' file.txt # 匹配 aaa
grep -E 'a{3,}' file.txt # 匹配 aaa、aaaa、aaaaa
grep -E 'a{2,4}' file.txt # 匹配 aa、aaa、aaaa
# 匹配IP地址
grep -E '[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}' file.txt
# 匹配邮箱
grep -E '[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,}' file.txt
# 匹配手机号
grep -E '1[3-9][0-9]{9}' file.txt
东巴文提示:使用-E选项启用扩展正则表达式,或使用egrep命令。
匹配IP地址:
#!/bin/bash
# 匹配IP地址
ip_pattern='([0-9]{1,3}\.){3}[0-9]{1,3}'
# 从文件中提取IP
grep -Eo $ip_pattern access.log
# 从命令输出中提取IP
ip addr show | grep -Eo $ip_pattern
# 验证IP地址格式
function is_valid_ip() {
local ip="$1"
if [[ $ip =~ ^([0-9]{1,3}\.){3}[0-9]{1,3}$ ]]; then
# 检查每个数字是否在0-255范围内
IFS='.' read -ra octets <<< "$ip"
for octet in "${octets[@]}"; do
if (( octet < 0 || octet > 255 )); then
return 1
fi
done
return 0
else
return 1
fi
}
# 测试
is_valid_ip "192.168.1.1" && echo "有效IP"
is_valid_ip "256.1.1.1" || echo "无效IP"
匹配邮箱地址:
#!/bin/bash
# 匹配邮箱地址
email_pattern='[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,}'
# 从文件中提取邮箱
grep -Eo $email_pattern contacts.txt
# 验证邮箱格式
function is_valid_email() {
local email="$1"
if [[ $email =~ ^[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,}$ ]]; then
return 0
else
return 1
fi
}
# 测试
is_valid_email "user@example.com" && echo "有效邮箱"
is_valid_email "invalid-email" || echo "无效邮箱"
匹配URL:
#!/bin/bash
# 匹配URL
url_pattern='https?://[a-zA-Z0-9.-]+(/[a-zA-Z0-9._~:/?#@!$&()*+,;=-]*)?'
# 从文件中提取URL
grep -Eo $url_pattern webpage.html
# 验证URL格式
function is_valid_url() {
local url="$1"
if [[ $url =~ ^https?://[a-zA-Z0-9.-]+ ]]; then
return 0
else
return 1
fi
}
# 测试
is_valid_url "https://www.example.com" && echo "有效URL"
is_valid_url "invalid-url" || echo "无效URL"
语法格式:
grep [选项] '模式' 文件
常用选项:
| 选项 | 说明 |
|---|---|
-i |
忽略大小写 |
-v |
反向匹配(显示不匹配的行) |
-n |
显示行号 |
-c |
只显示匹配的行数 |
-l |
只显示文件名 |
-w |
匹配整个单词 |
-x |
匹配整行 |
-o |
只显示匹配的部分 |
-E |
使用扩展正则表达式 |
-F |
固定字符串匹配(不使用正则) |
-r |
递归搜索目录 |
-A n |
显示匹配行及后n行 |
-B n |
显示匹配行及前n行 |
-C n |
显示匹配行及前后各n行 |
示例:
# 基本搜索
grep "root" /etc/passwd
# 忽略大小写
grep -i "ROOT" /etc/passwd
# 显示行号
grep -n "root" /etc/passwd
# 反向匹配
grep -v "nologin" /etc/passwd
# 只显示匹配行数
grep -c "root" /etc/passwd
# 匹配整个单词
grep -w "root" /etc/passwd
# 匹配整行
grep -x "root:x:0:0:root:/root:/bin/bash" /etc/passwd
# 只显示匹配的部分
grep -o "[0-9]\+" /etc/passwd
# 显示匹配行及后3行
grep -A 3 "root" /etc/passwd
# 显示匹配行及前3行
grep -B 3 "root" /etc/passwd
# 显示匹配行及前后各3行
grep -C 3 "root" /etc/passwd
东巴文理解:grep是最常用的文本搜索工具,掌握常用选项能提高效率。
搜索目录中的文件:
# 递归搜索目录
grep -r "error" /var/log/
# 递归搜索,只显示文件名
grep -rl "error" /var/log/
# 递归搜索,显示行号
grep -rn "error" /var/log/
# 指定文件类型
grep -r --include="*.log" "error" /var/log/
# 排除文件类型
grep -r --exclude="*.gz" "error" /var/log/
# 排除目录
grep -r --exclude-dir="archive" "error" /var/log/
实战案例:
#!/bin/bash
# 在代码中搜索函数定义
grep -rn "function\|def\|void" ./src/
# 在日志中搜索错误
grep -rn "ERROR\|FATAL\|CRITICAL" /var/log/
# 搜索配置文件中的设置
grep -rn "ServerName\|DocumentRoot" /etc/apache2/
# 搜索特定日期的日志
grep -rn "$(date +%Y-%m-%d)" /var/log/
使用多个模式:
# 匹配多个模式(或关系)
grep -E "error|warning|critical" /var/log/syslog
# 从文件读取模式
cat > patterns.txt << EOF
error
warning
critical
EOF
grep -f patterns.txt /var/log/syslog
# 匹配所有模式(与关系)
grep "error" /var/log/syslog | grep "database"
# 排除多个模式
grep -v -E "debug|info|notice" /var/log/syslog
显示匹配行的上下文:
# 显示匹配行及后5行
grep -A 5 "error" /var/log/syslog
# 显示匹配行及前5行
grep -B 5 "error" /var/log/syslog
# 显示匹配行及前后各5行
grep -C 5 "error" /var/log/syslog
# 显示多个匹配的上下文
grep -C 2 -E "error|warning" /var/log/syslog
统计匹配结果:
# 统计每个文件中的匹配行数
grep -c "error" /var/log/*.log
# 统计匹配的总行数
grep "error" /var/log/*.log | wc -l
# 统计匹配的文件数
grep -l "error" /var/log/*.log | wc -l
# 统计每个IP出现的次数
grep -oE '[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}' access.log | sort | uniq -c | sort -rn
# 统计每个URL的访问次数
grep -oE '/[a-zA-Z0-9./?=_-]*' access.log | sort | uniq -c | sort -rn | head -10
东巴文实战:结合sort、uniq等命令,可以进行强大的数据分析。
#!/bin/bash
#===============================================================================
# 脚本名称:log_analyzer.sh
# 脚本功能:日志分析脚本
# 作者:东巴文
#===============================================================================
LOG_FILE="/var/log/nginx/access.log"
echo "=== 日志分析报告 ==="
echo "生成时间:$(date)"
echo
# 1. 总请求数
total_requests=$(wc -l < "$LOG_FILE")
echo "总请求数:$total_requests"
# 2. 独立IP数
unique_ips=$(grep -oE '[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}' "$LOG_FILE" | sort -u | wc -l)
echo "独立IP数:$unique_ips"
# 3. 最常访问的IP(前10)
echo -e "\n最常访问的IP(前10):"
grep -oE '[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}' "$LOG_FILE" | sort | uniq -c | sort -rn | head -10
# 4. 最常访问的URL(前10)
echo -e "\n最常访问的URL(前10):"
awk '{print $7}' "$LOG_FILE" | sort | uniq -c | sort -rn | head -10
# 5. HTTP状态码统计
echo -e "\nHTTP状态码统计:"
awk '{print $9}' "$LOG_FILE" | sort | uniq -c | sort -rn
# 6. 404错误统计
echo -e "\n404错误统计:"
grep ' 404 ' "$LOG_FILE" | wc -l
# 7. 500错误统计
echo -e "\n500错误统计:"
grep ' 500 ' "$LOG_FILE" | wc -l
# 8. 按小时统计访问量
echo -e "\n按小时统计访问量:"
awk '{print substr($4, 14, 2)}' "$LOG_FILE" | sort | uniq -c
# 9. 按日期统计访问量
echo -e "\n按日期统计访问量:"
awk '{print substr($4, 2, 11)}' "$LOG_FILE" | sort | uniq -c
# 10. 搜索引擎爬虫统计
echo -e "\n搜索引擎爬虫统计:"
grep -iE 'googlebot|baiduspider|bingbot|yandexbot' "$LOG_FILE" | wc -l
#!/bin/bash
#===============================================================================
# 脚本名称:code_search.sh
# 脚本功能:代码搜索脚本
# 作者:东巴文
#===============================================================================
# 搜索函数定义
function search_function() {
local keyword="$1"
local directory="${2:-.}"
echo "搜索函数定义:$keyword"
grep -rn --include="*.py" --include="*.sh" --include="*.js" \
-E "(function|def|void)\s+$keyword" "$directory"
}
# 搜索变量定义
function search_variable() {
local keyword="$1"
local directory="${2:-.}"
echo "搜索变量定义:$keyword"
grep -rn --include="*.py" --include="*.sh" --include="*.js" \
-E "(var|let|const|=)\s*$keyword" "$directory"
}
# 搜索TODO注释
function search_todo() {
local directory="${1:-.}"
echo "搜索TODO注释:"
grep -rn --include="*.py" --include="*.sh" --include="*.js" \
-iE "TODO|FIXME|XXX|HACK" "$directory"
}
# 搜索错误处理
function search_error() {
local directory="${1:-.}"
echo "搜索错误处理:"
grep -rn --include="*.py" --include="*.sh" --include="*.js" \
-iE "error|exception|catch|try" "$directory"
}
# 主菜单
function main() {
local keyword="$1"
local directory="${2:-.}"
echo "=== 代码搜索工具 ==="
echo "关键词:$keyword"
echo "目录:$directory"
echo
search_function "$keyword" "$directory"
echo
search_variable "$keyword" "$directory"
}
# 执行
main "$@"
语法格式:
sed [选项] '命令' 文件
常用选项:
| 选项 | 说明 |
|---|---|
-n |
抑制自动输出 |
-e |
多点编辑 |
-f |
从文件读取脚本 |
-i |
直接修改文件 |
-r |
使用扩展正则表达式 |
常用命令:
| 命令 | 说明 |
|---|---|
p |
打印 |
d |
删除 |
s |
替换 |
a |
在指定行后追加 |
i |
在指定行前插入 |
c |
替换整行 |
y |
字符转换 |
示例:
# 打印第3行
sed -n '3p' /etc/passwd
# 打印第3到5行
sed -n '3,5p' /etc/passwd
# 打印最后一行
sed -n '$p' /etc/passwd
# 打印包含root的行
sed -n '/root/p' /etc/passwd
# 删除第3行
sed '3d' /etc/passwd
# 删除第3到5行
sed '3,5d' /etc/passwd
# 删除空行
sed '/^$/d' /etc/passwd
# 删除包含root的行
sed '/root/d' /etc/passwd
东巴文理解:sed是流编辑器,按行处理文本,不会修改原文件(除非使用-i选项)。
基本替换:
# 替换每行的第一个匹配
sed 's/old/new/' file.txt
# 替换每行的所有匹配
sed 's/old/new/g' file.txt
# 替换第2个匹配
sed 's/old/new/2' file.txt
# 替换第3到第5行的第一个匹配
sed '3,5s/old/new/' file.txt
# 只打印替换的行
sed -n 's/old/new/p' file.txt
# 忽略大小写
sed 's/old/new/gi' file.txt
# 直接修改文件
sed -i 's/old/new/g' file.txt
# 备份原文件后修改
sed -i.bak 's/old/new/g' file.txt
替换标志:
| 标志 | 说明 |
|---|---|
g |
全局替换 |
i |
忽略大小写 |
n |
替换第n个匹配 |
p |
打印替换的行 |
w file |
将替换结果写入文件 |
示例:
# 全局替换
sed 's/root/admin/g' /etc/passwd
# 忽略大小写替换
sed 's/ROOT/admin/gi' /etc/passwd
# 替换第2个匹配
sed 's/:/;/2' /etc/passwd
# 只打印替换的行
sed -n 's/root/admin/gp' /etc/passwd
# 将替换结果写入文件
sed -n 's/root/admin/gpw output.txt' /etc/passwd
行号定界:
# 处理第3行
sed '3s/old/new/' file.txt
# 处理第3到5行
sed '3,5s/old/new/' file.txt
# 处理最后一行
sed '$s/old/new/' file.txt
# 处理第3行到最后一行
sed '3,$s/old/new/' file.txt
# 处理奇数行
sed '1~2s/old/new/' file.txt
# 处理偶数行
sed '2~2s/old/new/' file.txt
模式定界:
# 处理包含pattern的行
sed '/pattern/s/old/new/' file.txt
# 处理从pattern1到pattern2的行
sed '/pattern1/,/pattern2/s/old/new/' file.txt
# 处理从第3行到包含pattern的行
sed '3,/pattern/s/old/new/' file.txt
# 处理不包含pattern的行
sed '/pattern/!s/old/new/' file.txt
使用-e选项:
# 多个替换操作
sed -e 's/old1/new1/g' -e 's/old2/new2/g' file.txt
# 删除和替换
sed -e '/^$/d' -e 's/old/new/g' file.txt
# 使用分号分隔
sed 's/old1/new1/g; s/old2/new2/g' file.txt
高级命令:
| 命令 | 说明 |
|---|---|
h |
复制模式空间到保持空间 |
H |
追加模式空间到保持空间 |
g |
复制保持空间到模式空间 |
G |
追加保持空间到模式空间 |
x |
交换模式空间和保持空间 |
n |
读取下一行到模式空间 |
N |
追加下一行到模式空间 |
示例:
# 反转文件行序
sed '1!G;h;$!d' file.txt
# 合并两行
sed 'N;s/\n/ /' file.txt
# 显示奇数行
sed 'n;d' file.txt
# 显示偶数行
sed '1d;n;d' file.txt
# 删除重复行
sed '$!N; /^\(.*\)\n\1$/!P; D' file.txt
东巴文提示:保持空间是sed的高级特性,可以实现复杂的文本处理。
#!/bin/bash
#===============================================================================
# 脚本名称:config_editor.sh
# 脚本功能:配置文件修改脚本
# 作者:东巴文
#===============================================================================
CONFIG_FILE="/etc/nginx/nginx.conf"
# 备份配置文件
cp "$CONFIG_FILE" "${CONFIG_FILE}.bak"
# 修改监听端口
sed -i 's/listen 80;/listen 8080;/' "$CONFIG_FILE"
# 修改worker进程数
sed -i 's/worker_processes auto;/worker_processes 4;/' "$CONFIG_FILE"
# 启用gzip压缩
sed -i 's/# gzip on;/gzip on;/' "$CONFIG_FILE"
# 添加server配置
sed -i '/server {/a\ listen 443 ssl;' "$CONFIG_FILE"
# 删除注释行
sed -i '/^[[:space:]]*#/d' "$CONFIG_FILE"
# 删除空行
sed -i '/^$/d' "$CONFIG_FILE"
echo "配置文件修改完成"
#!/bin/bash
#===============================================================================
# 脚本名称:log_processor.sh
# 脚本功能:日志处理脚本
# 作者:东巴文
#===============================================================================
LOG_FILE="/var/log/nginx/access.log"
# 1. 提取IP地址
echo "提取IP地址:"
sed -n 's/^\([0-9]\{1,3\}\.[0-9]\{1,3\}\.[0-9]\{1,3\}\.[0-9]\{1,3\}\).*/\1/p' "$LOG_FILE" | head -10
# 2. 提取URL
echo -e "\n提取URL:"
sed -n 's/.*"\([A-Z]\+\) \([^ ]*\) .*/\1 \2/p' "$LOG_FILE" | head -10
# 3. 提取HTTP状态码
echo -e "\n提取HTTP状态码:"
sed -n 's/.*" \([0-9]\{3\}\) .*/\1/p' "$LOG_FILE" | sort | uniq -c | sort -rn | head -10
# 4. 提取User-Agent
echo -e "\n提取User-Agent:"
sed -n 's/.*"\([^"]*\)"$/\1/p' "$LOG_FILE" | head -10
# 5. 替换敏感信息
echo -e "\n替换敏感信息:"
sed 's/[0-9]\{1,3\}\.[0-9]\{1,3\}\.[0-9]\{1,3\}\.[0-9]\{1,3\}/xxx.xxx.xxx.xxx/g' "$LOG_FILE" | head -5
# 6. 格式化日志
echo -e "\n格式化日志:"
sed 's/\[/%[/; s/\]/%]/' "$LOG_FILE" | head -5
#!/bin/bash
#===============================================================================
# 脚本名称:text_converter.sh
# 脚本功能:文本转换脚本
# 作者:东巴文
#===============================================================================
# 1. Windows换行符转Unix换行符
sed -i 's/\r$//' file.txt
# 2. Unix换行符转Windows换行符
sed -i 's/$/\r/' file.txt
# 3. 删除行首空格
sed 's/^[[:space:]]*//' file.txt
# 4. 删除行尾空格
sed 's/[[:space:]]*$//' file.txt
# 5. 删除行首和行尾空格
sed 's/^[[:space:]]*//;s/[[:space:]]*$//' file.txt
# 6. 删除HTML标签
sed 's/<[^>]*>//g' file.html
# 7. 提取HTML标签内容
sed -n 's/.*<title>\(.*\)<\/title>.*/\1/p' file.html
# 8. 大写转小写
sed 's/[A-Z]/\l&/g' file.txt
# 9. 小写转大写
sed 's/[a-z]/\u&/g' file.txt
# 10. 首字母大写
sed 's/\b\(.\)/\u\1/' file.txt
语法格式:
awk [选项] '模式 { 动作 }' 文件
常用选项:
| 选项 | 说明 |
|---|---|
-F |
指定字段分隔符 |
-v |
定义变量 |
-f |
从文件读取脚本 |
内置变量:
| 变量 | 说明 |
|---|---|
$0 |
整行内容 |
$1~$n |
第n个字段 |
NF |
字段数 |
NR |
行号 |
FNR |
文件行号 |
FS |
字段分隔符 |
RS |
记录分隔符 |
OFS |
输出字段分隔符 |
ORS |
输出记录分隔符 |
FILENAME |
文件名 |
示例:
# 打印整行
awk '{print $0}' /etc/passwd
# 打印第1个字段
awk -F: '{print $1}' /etc/passwd
# 打印第1和第7个字段
awk -F: '{print $1, $7}' /etc/passwd
# 打印行号和整行
awk '{print NR, $0}' /etc/passwd
# 打印字段数和整行
awk -F: '{print NF, $0}' /etc/passwd
# 打印最后一个字段
awk -F: '{print $NF}' /etc/passwd
# 打印倒数第2个字段
awk -F: '{print $(NF-1)}' /etc/passwd
东巴文理解:awk是强大的文本处理工具,按字段处理文本,支持编程。
使用模式:
# 匹配包含root的行
awk '/root/ {print $0}' /etc/passwd
# 匹配以root开头的行
awk '/^root/ {print $0}' /etc/passwd
# 匹配以bash结尾的行
awk /bash$/ {print $0}' /etc/passwd
# 匹配第3个字段为0的行
awk -F: '$3 == 0 {print $0}' /etc/passwd
# 匹配第3个字段大于等于1000的行
awk -F: '$3 >= 1000 {print $0}' /etc/passwd
# 匹配第1个字段为root或nginx的行
awk -F: '$1 == "root" || $1 == "nginx" {print $0}' /etc/passwd
# 匹配第7个字段包含bash的行
awk -F: '$7 ~ /bash/ {print $0}' /etc/passwd
# 匹配第7个字段不包含nologin的行
awk -F: '$7 !~ /nologin/ {print $0}' /etc/passwd
行号模式:
# 打印第3行
awk 'NR == 3 {print $0}' /etc/passwd
# 打印第3到5行
awk 'NR >= 3 && NR <= 5 {print $0}' /etc/passwd
# 打印奇数行
awk 'NR % 2 == 1 {print $0}' /etc/passwd
# 打印偶数行
awk 'NR % 2 == 0 {print $0}' /etc/passwd
# 打印前10行
awk 'NR <= 10 {print $0}' /etc/passwd
# 打印最后一行
awk 'END {print $0}' /etc/passwd
if-else语句:
# 条件判断
awk -F: '{
if ($3 == 0) {
print $1 " is root"
} else if ($3 >= 1000) {
print $1 " is normal user"
} else {
print $1 " is system user"
}
}' /etc/passwd
# 简写
awk -F: '$3 == 0 {print $1 " is root"} $3 >= 1000 {print $1 " is normal user"}' /etc/passwd
条件运算符:
# 三目运算符
awk -F: '{print $1, ($3 == 0) ? "root" : "user"}' /etc/passwd
# 逻辑运算符
awk -F: '$3 >= 1000 && $3 < 65534 {print $1}' /etc/passwd
awk -F: '$3 == 0 || $3 == 65534 {print $1}' /etc/passwd
for循环:
# 遍历字段
awk -F: '{
for (i = 1; i <= NF; i++) {
print "Field " i ": " $i
}
}' /etc/passwd
# 计算总和
awk '{
sum = 0
for (i = 1; i <= NF; i++) {
sum += $i
}
print "Sum:", sum
}' numbers.txt
while循环:
# while循环
awk -F: '{
i = 1
while (i <= NF) {
print "Field " i ": " $i
i++
}
}' /etc/passwd
# do-while循环
awk -F: '{
i = 1
do {
print "Field " i ": " $i
i++
} while (i <= NF)
}' /etc/passwd
数组操作:
# 统计每个shell的用户数
awk -F: '{
shell[$7]++
}
END {
for (s in shell) {
print s ": " shell[s]
}
}' /etc/passwd
# 统计每个IP的访问次数
awk '{
ip[$1]++
}
END {
for (i in ip) {
print i ": " ip[i]
}
}' access.log
# 统计每个URL的访问次数
awk '{
url[$7]++
}
END {
for (u in url) {
print u ": " url[u]
}
}' access.log
东巴文提示:awk的数组是关联数组,可以使用字符串作为索引。
常用字符串函数:
| 函数 | 说明 | 示例 |
|---|---|---|
length(s) |
字符串长度 | length("hello") → 5 |
substr(s, i, n) |
子字符串 | substr("hello", 2, 3) → "ell" |
index(s, t) |
子串位置 | index("hello", "ll") → 3 |
split(s, a, fs) |
分割字符串 | split("a:b:c", arr, ":") |
sub(r, s, t) |
替换第一个匹配 | sub(/old/, "new", $0) |
gsub(r, s, t) |
替换所有匹配 | gsub(/old/, "new", $0) |
tolower(s) |
转小写 | tolower("HELLO") → "hello" |
toupper(s) |
转大写 | toupper("hello") → "HELLO" |
sprintf(fmt, ...) |
格式化字符串 | sprintf("%d", 10) → "10" |
示例:
# 字符串长度
awk '{print length($0)}' /etc/passwd
# 提取子字符串
awk -F: '{print substr($1, 1, 3)}' /etc/passwd
# 查找子串位置
awk -F: '{print index($0, "root")}' /etc/passwd
# 分割字符串
awk -F: '{
n = split($7, arr, "/")
for (i = 1; i <= n; i++) {
print arr[i]
}
}' /etc/passwd
# 替换字符串
awk -F: '{sub(/root/, "admin"); print $0}' /etc/passwd
awk -F: '{gsub(/root/, "admin"); print $0}' /etc/passwd
# 大小写转换
awk -F: '{print toupper($1)}' /etc/passwd
awk -F: '{print tolower($1)}' /etc/passwd
常用数值函数:
| 函数 | 说明 | 示例 |
|---|---|---|
int(x) |
取整 | int(3.7) → 3 |
sqrt(x) |
平方根 | sqrt(16) → 4 |
exp(x) |
e的x次方 | exp(1) → 2.71828 |
log(x) |
自然对数 | log(10) → 2.30259 |
sin(x) |
正弦 | sin(0) → 0 |
cos(x) |
余弦 | cos(0) → 1 |
rand() |
随机数 | rand() → 0-1之间的随机数 |
srand(x) |
设置随机种子 | srand() |
示例:
# 取整
awk '{print int($1)}' numbers.txt
# 平方根
awk '{print sqrt($1)}' numbers.txt
# 随机数
awk 'BEGIN {srand(); for (i=1; i<=10; i++) print int(rand()*100)}'
时间函数:
| 函数 | 说明 |
|---|---|
systime() |
当前时间戳 |
mktime(datespec) |
时间戳转换 |
strftime(format, timestamp) |
格式化时间 |
示例:
# 当前时间戳
awk 'BEGIN {print systime()}'
# 格式化时间
awk 'BEGIN {print strftime("%Y-%m-%d %H:%M:%S", systime())}'
# 时间计算
awk 'BEGIN {
now = systime()
tomorrow = now + 86400
print "今天:", strftime("%Y-%m-%d", now)
print "明天:", strftime("%Y-%m-%d", tomorrow)
}'
#!/bin/bash
#===============================================================================
# 脚本名称:log_analyzer_awk.sh
# 脚本功能:使用awk分析日志
# 作者:东巴文
#===============================================================================
LOG_FILE="/var/log/nginx/access.log"
echo "=== Nginx访问日志分析 ==="
# 1. 总请求数
echo -e "\n总请求数:"
awk 'END {print NR}' "$LOG_FILE"
# 2. 独立IP数
echo -e "\n独立IP数:"
awk '{ip[$1]++} END {for (i in ip) count++} END {print count}' "$LOG_FILE"
# 3. 最常访问的IP(前10)
echo -e "\n最常访问的IP(前10):"
awk '{ip[$1]++} END {for (i in ip) print ip[i], i}' "$LOG_FILE" | sort -rn | head -10
# 4. 最常访问的URL(前10)
echo -e "\n最常访问的URL(前10):"
awk '{url[$7]++} END {for (u in url) print url[u], u}' "$LOG_FILE" | sort -rn | head -10
# 5. HTTP状态码统计
echo -e "\nHTTP状态码统计:"
awk '{status[$9]++} END {for (s in status) print status[s], s}' "$LOG_FILE" | sort -rn
# 6. 平均响应时间
echo -e "\n平均响应时间:"
awk '{sum+=$NF; count++} END {print sum/count " ms"}' "$LOG_FILE"
# 7. 按小时统计访问量
echo -e "\n按小时统计访问量:"
awk '{hour[substr($4, 14, 2)]++} END {for (h in hour) print h, hour[h]}' "$LOG_FILE" | sort
# 8. 按日期统计访问量
echo -e "\n按日期统计访问量:"
awk '{date[substr($4, 2, 11)]++} END {for (d in date) print d, date[d]}' "$LOG_FILE" | sort
# 9. 统计每个IP的流量
echo -e "\n统计每个IP的流量(前10):"
awk '{traffic[$1]+=$10} END {for (i in traffic) print traffic[i], i}' "$LOG_FILE" | sort -rn | head -10
# 10. 统计User-Agent
echo -e "\n统计User-Agent(前10):"
awk '{gsub(/"/, "", $12); ua[$12]++} END {for (u in ua) print ua[u], u}' "$LOG_FILE" | sort -rn | head -10
#!/bin/bash
#===============================================================================
# 脚本名称:data_processor.sh
# 脚本功能:数据处理脚本
# 作者:东巴文
#===============================================================================
# 1. 计算平均值
echo "计算平均值:"
awk '{sum+=$1; count++} END {print "Average:", sum/count}' numbers.txt
# 2. 计算最大值
echo -e "\n计算最大值:"
awk 'BEGIN {max=0} {if ($1>max) max=$1} END {print "Max:", max}' numbers.txt
# 3. 计算最小值
echo -e "\n计算最小值:"
awk 'BEGIN {min=999999} {if ($1<min) min=$1} END {print "Min:", min}' numbers.txt
# 4. 计算总和
echo -e "\n计算总和:"
awk '{sum+=$1} END {print "Sum:", sum}' numbers.txt
# 5. 统计行数
echo -e "\n统计行数:"
awk 'END {print "Total lines:", NR}' numbers.txt
# 6. 统计字段数
echo -e "\n统计字段数:"
awk '{print "Line", NR, "has", NF, "fields"}' data.txt
# 7. 过滤数据
echo -e "\n过滤大于100的数据:"
awk '$1 > 100 {print $0}' numbers.txt
# 8. 数据排序
echo -e "\n数据排序:"
awk '{print $0}' numbers.txt | sort -n
# 9. 去重
echo -e "\n去重:"
awk '!seen[$0]++' data.txt
# 10. 数据格式化
echo -e "\n数据格式化:"
awk '{printf "%-10s %10d %10.2f\n", $1, $2, $3}' data.txt
#!/bin/bash
#===============================================================================
# 脚本名称:system_monitor.sh
# 脚本功能:系统监控脚本
# 作者:东巴文
#===============================================================================
echo "=== 系统监控报告 ==="
echo "生成时间:$(date)"
echo
# 1. CPU使用率
echo "CPU使用率:"
top -bn1 | awk '/Cpu(s)/ {
printf "用户: %.1f%%\n", $2
printf "系统: %.1f%%\n", $4
printf "空闲: %.1f%%\n", $8
}'
# 2. 内存使用
echo -e "\n内存使用:"
free | awk '/Mem:/ {
total=$2/1024
used=$3/1024
free=$4/1024
printf "总计: %.1f MB\n", total
printf "已用: %.1f MB\n", used
printf "空闲: %.1f MB\n", free
printf "使用率: %.1f%%\n", (used/total)*100
}'
# 3. 磁盘使用
echo -e "\n磁盘使用:"
df -h | awk '/^\/dev/ {
printf "%-20s %10s %10s %10s %10s\n", $1, $2, $3, $4, $5
}'
# 4. 网络连接
echo -e "\n网络连接统计:"
netstat -an | awk '/^tcp/ {
state[$6]++
}
END {
for (s in state) {
print s ": " state[s]
}
}'
# 5. 进程统计
echo -e "\n进程统计:"
ps aux | awk 'NR>1 {
user[$1]++
}
END {
for (u in user) {
print u ": " user[u]
}
}'
# 6. 用户登录
echo -e "\n用户登录:"
who | awk '{print $1, $2, $3, $4}'
# 7. 系统负载
echo -e "\n系统负载:"
awk '{print "1分钟:", $1, "5分钟:", $2, "15分钟:", $3}' /proc/loadavg
# 8. 网络流量
echo -e "\n网络流量:"
awk '/eth0:/ {
printf "接收: %.2f MB\n", $2/1024/1024
printf "发送: %.2f MB\n", $10/1024/1024
}' /proc/net/dev
✅ 掌握正则表达式语法 ✅ 熟练使用grep搜索文本 ✅ 学会sed编辑文本 ✅ 掌握awk处理文本
完成本章学习后,请确认您能够:
东巴文(db-w.cn) - 让Linux学习更简单