egrep(extended grep)命令是grep家族的一员,它使用扩展正则表达式(Extended Regular Expressions)进行模式匹配。与基本的grep命令相比,egrep支持更多的元字符和操作符,使得模式匹配更加灵活和强大。
egrep 通常等同于 grep -E,建议在新脚本中使用 grep -E 以获得更好的兼容性。
egrep [选项] 模式 [文件...]
grep -E [选项] 模式 [文件...]
| 选项 | 说明 |
|---|---|
| -i | 忽略大小写 |
| -v | 反向匹配,显示不包含模式的行 |
| -c | 只显示匹配行的计数 |
| -n | 显示匹配行的行号 |
| -l | 只显示包含匹配模式的文件名 |
| -L | 只显示不包含匹配模式的文件名 |
| -r | 递归搜索子目录 |
| -w | 匹配整个单词 |
| -x | 匹配整行 |
| -A num | 显示匹配行后的num行 |
| -B num | 显示匹配行前的num行 |
| -C num | 显示匹配行前后的num行 |
| -o | 只输出匹配的部分 |
| -h | 不显示文件名前缀 |
| -H | 显示文件名前缀 |
| 元字符 | 说明 | 示例 |
|---|---|---|
| + | 匹配前一个字符1次或多次 | go+d 匹配 god, good, goood 等 |
| ? | 匹配前一个字符0次或1次 | colou?r 匹配 color 和 colour |
| | | 或操作,匹配多个模式之一 | cat|dog 匹配 cat 或 dog |
| () | 分组,将模式组合在一起 | (abc)+ 匹配 abc, abcabc 等 |
| {} | 指定匹配次数范围 | a{2,4} 匹配 aa, aaa, aaaa |
| \b | 单词边界 | \bword\b 匹配完整单词 word |
| \< \> | 单词开始和结束 | \<word 匹配以word开头的单词 |
| [] | 字符类,匹配括号内任意字符 | [aeiou] 匹配任意元音字母 |
| [^] | 否定字符类 | [^0-9] 匹配非数字字符 |
| ^ | 行开始 | ^Hello 匹配行首的Hello |
| $ | 行结束 | world$ 匹配行尾的world |
| . | 匹配任意单个字符 | a.c 匹配 abc, adc, aec 等 |
| * | 匹配前一个字符0次或多次 | ab*c 匹配 ac, abc, abbc 等 |
在文件中搜索匹配模式的行:
# 创建测试文件
echo -e "apple\nbanana\ncherry\ndate\nelderberry" > fruits.txt
echo -e "123 apple 456\nbanana split\ncherry pie" >> fruits.txt
# 基本搜索
egrep "apple" fruits.txt
# 忽略大小写搜索
egrep -i "APPLE" fruits.txt
# 显示行号
egrep -n "berry" fruits.txt
利用扩展正则表达式的强大功能:
# 创建包含各种格式的测试文件
cat > data.txt << 'EOF'
color
colour
cat
dog
bat
bet
bit
boot
feet
food
EOF
# 使用 | 进行或匹配
egrep "cat|dog" data.txt
# 使用 ? 进行可选匹配
egrep "colou?r" data.txt
# 使用 + 匹配一次或多次
egrep "bo+t" data.txt
# 使用 {} 指定匹配次数
egrep "b[aeiou]{1,2}t" data.txt
使用分组和复杂模式:
# 创建包含多种格式的文件
cat > contacts.txt << 'EOF'
John Doe: 555-1234
Jane Smith: (555) 567-8901
Bob Johnson: 555.7890
Alice Brown: 555-4321 ext 123
EOF
# 匹配不同格式的电话号码
egrep "\(?[0-9]{3}\)?[-. ]?[0-9]{3,4}[-. ]?[0-9]{4}" contacts.txt
# 匹配姓名和电话号码
egrep "^[A-Z][a-z]+ [A-Z][a-z]+:" contacts.txt
# 使用分组提取特定部分
egrep -o "([0-9]{3})[-. ]([0-9]{3,4})" contacts.txt
分析日志文件和配置文件:
# 创建示例日志文件
cat > app.log << 'EOF'
2024-01-01 10:00:00 INFO Application started
2024-01-01 10:00:01 ERROR Database connection failed
2024-01-01 10:00:02 WARNING High memory usage
2024-01-01 10:00:03 INFO User login successful
2024-01-01 10:00:04 ERROR File not found
2024-01-01 10:00:05 DEBUG Processing request
EOF
# 搜索错误日志
egrep "ERROR" app.log
# 搜索特定时间范围的日志
egrep "10:00:0[0-2]" app.log
# 统计各类日志数量
echo "错误数量: $(egrep -c "ERROR" app.log)"
echo "警告数量: $(egrep -c "WARNING" app.log)"
echo "信息数量: $(egrep -c "INFO" app.log)"
在目录树中递归搜索文件:
# 创建测试目录结构
mkdir -p test/{src,doc,bin}
echo "TODO: fix this function" > test/src/main.c
echo "TODO: update documentation" > test/doc/readme.txt
echo "function calculate() {" > test/src/utils.c
echo "TODO: optimize algorithm" > test/src/algorithm.c
# 递归搜索包含TODO的文件
egrep -r "TODO" test/
# 只显示文件名
egrep -rl "TODO" test/
# 搜索并显示上下文
egrep -r -A1 -B1 "function" test/src/
结合其他命令进行复杂文本处理:
# 提取代码中的函数定义
cat > example.py << 'EOF'
def calculate_sum(a, b):
return a + b
class Calculator:
def __init__(self):
self.value = 0
def add(self, x):
self.value += x
def multiply(x, y):
return x * y
EOF
# 提取所有函数定义
egrep "^def [a-zA-Z_][a-zA-Z0-9_]*" example.py
# 提取类中的方法
egrep "def [a-zA-Z_][a-zA-Z0-9_]*\(self" example.py
# 提取函数名
egrep -o "def ([a-zA-Z_][a-zA-Z0-9_]*)" example.py | cut -d' ' -f2
实时监控和分析系统日志:
#!/bin/bash
# 监控错误日志并发送警报
monitor_errors() {
local log_file=$1
local alert_threshold=5
echo "开始监控日志文件: $log_file"
# 实时监控日志中的错误
tail -f "$log_file" | while read line; do
if echo "$line" | egrep -q "ERROR|CRITICAL|FATAL"; then
echo "发现错误: $line"
# 这里可以添加发送警报的代码
fi
done
}
# 统计错误类型
analyze_errors() {
local log_file=$1
echo "错误分析报告:"
echo "==============="
# 统计各种错误类型
egrep -o "ERROR [A-Z_]+" "$log_file" | sort | uniq -c | sort -nr
# 统计错误时间分布
echo -e "\n错误时间分布:"
egrep "ERROR" "$log_file" | cut -d' ' -f1,2 | sort | uniq -c
}
# 使用函数
analyze_errors "/var/log/syslog"
在代码库中搜索潜在问题:
#!/bin/bash
# 代码质量检查脚本
code_review() {
local code_dir=$1
echo "代码审查报告: $code_dir"
echo "===================="
# 搜索TODO和FIXME注释
echo -e "\n待办事项:"
egrep -r -n "TODO|FIXME" "$code_dir" | head -10
# 搜索调试代码
echo -e "\n可能的调试代码:"
egrep -r -n "print\(|console\.log|alert\(" "$code_dir" | head -10
# 搜索硬编码的密码和密钥
echo -e "\n可能的敏感信息:"
egrep -r -i "password|secret|key|token" "$code_dir" | \
egrep -v ".git|node_modules" | head -10
# 搜索长函数(超过50行)
echo -e "\n长函数检查:"
find "$code_dir" -name "*.py" -exec awk '
/^def [a-zA-Z_]/ {
if (lines > 50) print filename ":" NR-lines-1 ": 函数超过50行 (" lines "行)";
lines=0; func=$0; filename=FILENAME
}
{ lines++ }
END { if (lines > 50) print filename ": 最后一个函数超过50行 (" lines "行)" }
' {} \;
}
# 使用函数
code_review "/path/to/project"
从结构化文本中提取数据:
#!/bin/bash
# 从各种格式中提取电子邮件地址
extract_emails() {
local input_file=$1
local output_file=$2
echo "提取电子邮件地址..."
# 使用扩展正则表达式匹配电子邮件格式
egrep -o "[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,}" "$input_file" | \
sort | uniq > "$output_file"
echo "找到 $(wc -l < "$output_file") 个唯一的电子邮件地址"
echo "结果保存到: $output_file"
}
# 提取URL链接
extract_urls() {
local input_file=$1
local output_file=$2
echo "提取URL链接..."
# 匹配常见的URL格式
egrep -o "https?://[a-zA-Z0-9./?=_-]+" "$input_file" | \
sort | uniq > "$output_file"
echo "找到 $(wc -l < "$output_file") 个唯一的URL"
echo "结果保存到: $output_file"
}
# 使用函数
extract_emails "document.txt" "emails.txt"
extract_urls "webpage.html" "urls.txt"
提高egrep搜索效率的技巧:
# 使用更具体的模式(提高搜索速度)
egrep "^[A-Z][a-z]+ [A-Z][a-z]+:" file.txt # 好的:具体模式
egrep ".*name.*" file.txt # 差的:过于宽泛
# 使用单词边界避免部分匹配
egrep -w "word" file.txt # 只匹配完整单词
egrep "\bword\b" file.txt # 同上,使用单词边界
# 限制搜索范围
egrep -m 100 "pattern" large_file.txt # 最多显示100个匹配
egrep "pattern" file.txt | head -50 # 只显示前50个结果
构建复杂的正则表达式模式:
# 匹配IPv4地址
egrep "([0-9]{1,3}\.){3}[0-9]{1,3}" file.txt
# 匹配日期格式 (YYYY-MM-DD)
egrep "[0-9]{4}-[0-9]{2}-[0-9]{2}" file.txt
# 匹配信用卡号码模式
egrep "[0-9]{4}[- ]?[0-9]{4}[- ]?[0-9]{4}[- ]?[0-9]{4}" file.txt
# 匹配HTML标签(简单版本)
egrep -o "<[a-zA-Z][a-zA-Z0-9]*[^>]*>" file.html
将egrep与awk、sed等工具结合使用:
# 结合awk进行高级处理
egrep "ERROR" app.log | awk '{print $1, $2, $5}'
# 结合sed进行替换
egrep -l "old_pattern" *.txt | xargs sed -i 's/old_pattern/new_pattern/g'
# 结合sort和uniq进行统计
egrep -o "[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}" log.txt | \
sort | uniq -c | sort -nr
grep -E 代替 egrep 以获得更好的兼容性-r 选项递归搜索时,注意排除不需要的目录(如.git, node_modules等)fgrep(或 grep -F)来搜索固定字符串,速度更快正确处理正则表达式中的特殊字符:
# 匹配包含点的字符串(点需要转义)
egrep "example\.com" file.txt
# 匹配包含方括号的字符串
egrep "\[important\]" file.txt
# 匹配包含反斜杠的字符串
egrep "\\\\" file.txt # 需要四个反斜杠
# 使用-F选项匹配固定字符串(避免转义问题)
grep -F "special.chars[]" file.txt
优化egrep性能:
# 使用更具体的锚点
egrep "^pattern" file.txt # 从行首开始匹配,更快
egrep "pattern$" file.txt # 匹配行尾
# 避免使用.*开头的模式
egrep "specific.*pattern" file.txt # 好的
egrep ".*pattern" file.txt # 差的
# 使用LC_ALL=C提高ASCII文本搜索速度
LC_ALL=C egrep "pattern" file.txt
# 对大文件使用split分割后并行处理
split -l 10000 large_file.txt chunk_
for file in chunk_*; do
egrep "pattern" "$file" >> results.txt &
done
wait
处理不同编码的文本文件:
# 指定文件编码
egrep "pattern" file.txt --encoding=UTF-8
# 处理二进制文件中的文本
strings binary_file | egrep "pattern"
# 转换文件编码后搜索
iconv -f ISO-8859-1 -t UTF-8 file.txt | egrep "pattern"
# 使用file命令检查文件编码
file -i unknown_file.txt
| 命令 | 说明 | 区别 |
|---|---|---|
| grep | 基本正则表达式搜索 | 使用基本正则表达式,功能较少 |
| fgrep | 固定字符串搜索 | 不解析正则表达式,速度更快 |
| ack | 代码搜索工具 | 专为搜索代码优化,自动忽略版本控制目录 |
| ag | Silver Searcher | 比ack更快的代码搜索工具 |
| rg | ripgrep | 目前最快的搜索工具,支持正则表达式 |
| sed | 流编辑器 | 可以进行文本替换和转换 |
| awk | 文本处理语言 | 更适合复杂的文本处理和数据提取 |
虽然 egrep 仍然被广泛支持,但在新脚本中建议使用 grep -E 以获得更好的兼容性。对于性能要求高的场景,可以考虑使用更现代的搜索工具如 rg(ripgrep)。