Linux三剑客:grep、sed、awk 详解以及find区别

发布于:2025-07-05 ⋅ 阅读:(14) ⋅ 点赞:(0)

grep、sed、awk是Linux/Unix系统中经典的文本处理工具,合称“三剑客”。三者各有所长:

  • grep:擅长文本搜索(过滤)。
  • sed:擅长文本编辑(替换、删除等)。
  • awk:擅长文本分析(格式化输出、计算等)

一、grep:文本搜索

1. 基本语法

  • 用途​​:在​​文件内容​​中搜索匹配特定模式的文本(支持正则表达式)。
  • ​工作对象​​:文件内容(文本)。
  • 常用选项​​:
    选项 作用 示例
    -i 忽略大小写 grep -i "error" file.log
    -r 递归搜索目录 grep -r "TODO" ./src
    -n 显示匹配行的行号 grep -n "warning" app.log
    -v 反向匹配(输出​​不包含​​模式的行) grep -v "debug" output.log
    -l 仅输出包含匹配项的文件名 grep -rl "FIXME" ./code
    -E 启用扩展正则表达式(等价于egrep `grep -E "err

2. 示例

我们假设存在名为file.txt的文件,对该文件进行grep命令操作,文件内容如下

hello world
Hello Universe
start here
mission complete
hallo and hello
goodbye end

执行以下命令:

# 在文件中搜索基础文本
grep "hello" file.txt           # 输出:hello world, hallo and hello
grep -i "hello" file.txt        # 输出:hello world, Hello Universe, hallo and hello
grep -n "hello" file.txt        # 输出:1:hello world, 5:hallo and hello

# 递归搜索目录
grep -r "TODO" ./src            # 搜索./src目录下所有文件中的"TODO"

# 使用正则表达式
grep "^start" file.txt          # 搜索以start开头的行 → "start here"
grep "end$" file.txt            # 搜索以end结尾的行 → "goodbye end"
grep "he[ae]llo" file.txt       # 匹配hello或hallo → "hello world", "hallo and hello"
grep -E "hello|complete" file.txt  # 匹配hello或complete → "hello world", "mission complete", "hallo and hello"
grep "[A-Z]" file.txt           # 搜索包含大写字母的行 → "Hello Universe", "mission complete"

二、sed:文本替换与转换​

​1. 基本语法​

  • ​用途​​:对输入流(文件或管道)进行​​文本替换、删除、插入、打印​​等操作

  • ​工作模式​​:逐行处理文本,默认输出到标准输出(不修改源文件)

  • ​常用选项​​:

    选项 作用 示例
    -e 指定编辑命令 sed -e 's/a/A/' file
    -n 抑制默认输出(常与p命令配合) sed -n '1,3p' file
    -i 原地修改文件(可选备份后缀) sed -i.bak 's/old/new/' file
    -r 启用扩展正则表达式 sed -r 's/(abc)/\U\1/' file
  • ​常用命令​​:

    命令 作用 示例
    s/regex/replacement/ 替换匹配的文本 sed 's/old/new/' file
    d 删除行 sed '3d' file
    p 打印行 sed -n '1,5p' file
    a\text 在行后追加文本 sed '2a\new line' file
    i\text 在行前插入文本 sed '3i\inserted' file
    y/abc/ABC/ 字符转换(类似tr) sed 'y/a-z/A-Z/' file

​2. 示例​

假设存在名为 demo.txt 的文件,内容为:

hello world
Hello Universe
start here
mission complete
hallo and hello
goodbye end

​基础操作​​:

# 1. 替换文本(每行第一个匹配)
sed 's/hello/HELLO/' demo.txt
# 输出:
# HELLO world
# Hello Universe
# start here
# mission complete
# hallo and HELLO
# goodbye end

# 2. 全局替换(使用g标志)
sed 's/hello/HELLO/g' demo.txt
# 输出:
# HELLO world
# Hello Universe
# start here
# mission complete
# hallo and HELLO
# goodbye end

# 3. 删除行(删除第3行)
sed '3d' demo.txt
# 输出:
# hello world
# Hello Universe
# mission complete
# hallo and hello
# goodbye end

# 4. 打印特定行(打印2-4行)
sed -n '2,4p' demo.txt
# 输出:
# Hello Universe
# start here
# mission complete

​正则表达式操作​​:

# 1. 替换以"s"开头的行
sed '/^s/ s/here/HERE/' demo.txt
# 输出:第三行 → start HERE

# 2. 删除包含"complete"的行
sed '/complete/d' demo.txt
# 输出中无第四行

# 3. 在"hallo"行前插入文本
sed '/hallo/i\--INSERT BEFORE--' demo.txt
# 在第五行前插入:--INSERT BEFORE--

# 4. 在"goodbye"行后追加文本
sed '/goodbye/a\--APPEND AFTER--' demo.txt
# 在第六行后追加:--APPEND AFTER--

​高级操作​​:

# 1. 使用反向引用(保留部分内容)
echo "2023-01-15" | sed -r 's/([0-9]{4})-([0-9]{2})-([0-9]{2})/\3.\2.\1/'
# 输出:15.01.2023

# 2. 仅修改第2-4行
sed '2,4 s/o/O/g' demo.txt
# 输出:
# hello world
# HellO Universe
# start here
# missiOn cOmplete
# hallo and hello
# goodbye end

# 3. 多重操作(使用-e)
sed -e 's/hello/HELLO/' -e '3d' demo.txt
# 先替换hello再删除第3行

# 4. 字符转换(小写转大写)
sed 'y/abcdefghijklmnopqrstuvwxyz/ABCDEFGHIJKLMNOPQRSTUVWXYZ/' demo.txt
# 全转大写

​文件操作​​:

# 1. 修改文件并备份(GNU sed)
sed -i.bak 's/hello/HELLO/g' demo.txt  # 生成demo.txt.bak备份

# 2. 直接修改文件(无备份)
sed -i 's/hello/HELLO/g' demo.txt

​3. 使用技巧​

  1. ​测试命令​​:先用不带 -i 的命令测试,确认无误后再用 -i
  2. ​转义特殊字符​​:对 /&. 等使用反斜杠转义
  3. ​跨行处理​​:使用 N 命令读入多行(如 sed 'N; s/\n//'
  4. ​组合命令​​:用分号分隔多个命令 sed 's/a/A/; 3d' file

⚠️ ​​警告​​:使用 -i 时务必先备份,避免不可逆的数据丢失!

​三、awk:文本分析​

​1. 基本语法​

  • ​用途​​:对文本进行​​模式扫描和处理​​,适用于结构化的文本数据(如按列处理)

  • ​工作模式​​:逐行扫描文件,对匹配模式的每行执行指定动作(默认动作为打印当前行)

  • ​核心概念​​:

    • ​字段(Field)​​:通过分隔符自动拆分的文本单元($1$2...表示)
    • ​记录(Record)​​:默认以换行符分隔的行(可通过RS变量修改)
  • ​语法结构​​:

    awk '模式 {动作}' 文件名
    # 或使用单行命令
    awk -F: '{print $1}' /etc/passwd
  • ​常用内置变量​​:

    变量 作用 示例
    $0 整行内容 awk '{print $0}' file
    $n 第n个字段(n=1,2,3...) awk '{print $3}' file
    NR 当前行号(记录号) awk '{print NR, $0}' file
    NF 当前行的字段数量 awk '{print NF}' file
    FS 输入字段分隔符(默认空格) awk 'BEGIN{FS=":"}...'
    OFS 输出字段分隔符(默认空格) awk 'BEGIN{OFS="-"}{print $1,$2}'
    FILENAME 当前处理文件名 awk '{print FILENAME}' file
  • ​常用选项​​:

    选项 作用 示例
    -F 设置字段分隔符 awk -F',' '{print $2}' data.csv
    -v 定义awk变量 awk -v name="Alice" '/name/ {print name}'
  • ​特殊模式​​:

    模式 作用
    BEGIN 处理文本前执行的动作
    END 处理完所有文本后执行的动作

​2. 示例​

假设存在名为 employees.txt 的文件,内容为:

Alice Johnson|28|Engineer|55000
Bob Smith|32|Manager|72000
Carol Davis|25|Designer|48000

​基础操作​​:

# 1. 打印整行
awk '{print $0}' employees.txt

# 2. 打印第一列(默认空格分隔,效果不佳)
awk '{print $1}' employees.txt

# 3. 设置分隔符为"|",打印姓名
awk -F'|' '{print $1}' employees.txt
# 输出:
# Alice Johnson
# Bob Smith
# Carol Davis

# 4. 打印行号和第3列
awk -F'|' '{print NR, $3}' employees.txt
# 输出:
# 1 Engineer
# 2 Manager
# 3 Designer

# 5. 打印最后一行(END模式)
awk -F'|' 'END{print "Last employee:", $1}' employees.txt
# 输出:Last employee: Carol Davis

​条件过滤​​:

# 1. 筛选年龄>30的员工
awk -F'|' '$2 > 30 {print $1}' employees.txt
# 输出:Bob Smith

# 2. 筛选工程师
awk -F'|' '$3 == "Engineer" {print $1, "($4)"}' employees.txt
# 输出:Alice Johnson (55000)

# 3. 使用正则:匹配姓氏含"S"的员工
awk -F'|' '$1 ~ /S/ {print $1}' employees.txt
# 输出:Bob Smith

​计算与统计​​:

# 1. 计算平均工资
awk -F'|' 'NR>1 {sum+=$4; count++} END{print "Avg Salary:", sum/count}' employees.txt
# 输出:Avg Salary: 58333.3

# 2. 格式化输出(设置OFS)
awk -F'|' 'BEGIN{OFS=" | "} {print NR, $1, "Salary: $" $4}' employees.txt
# 输出:
# 1 | Alice Johnson | Salary: $55000
# 2 | Bob Smith | Salary: $72000
# 3 | Carol Davis | Salary: $48000

# 3. 统计岗位数量(使用数组)
awk -F'|' 'NR>1 {jobs[$3]++} END{for(j in jobs) print j, jobs[j] " person(s)"}' employees.txt
# 输出:
# Engineer 1 person(s)
# Manager 1 person(s)
# Designer 1 person(s)

​BEGIN块初始化​​:

# 添加表头行和美元符号
awk -F'|' 'BEGIN {print "ID | Name | Position | Salary\n--------------------------"} 
           NR>1 {print NR-1, $1, $3, "$" $4}' employees.txt
# 输出:
# ID | Name | Position | Salary
# --------------------------
# 1 Alice Johnson Engineer $55000
# 2 Bob Smith Manager $72000
# 3 Carol Davis Designer $48000

​3. 高级技巧​

  1. ​内置函数​​:
    # 转换小写
    echo "HELLO" | awk '{print tolower($0)}'  # → hello
    
    # 字符串截取
    awk -F'|' '{print substr($1, 1, 3)}' employees.txt  # → Ali, Bob, Car
  2. ​条件语句​​:
    # 工资分级
    awk -F'|' '{
      if ($4 > 60000) status="High"
      else if ($4 > 50000) status="Medium"
      else status="Low"
      print $1, ":", status
    }' employees.txt
  3. ​多文件处理​​:
    # 同时处理两个文件(行号重置)
    awk '{print FILENAME, NR, "->", $0}' file1.txt file2.txt
  4. ​处理复杂日志​​:
    # 统计Nginx日志中每个IP的访问量
    awk '{ip_count[$1]++} END{for(i in ip_count) print i, ip_count[i]}' access.log

​4. 常见应用场景​

场景 awk命令
提取CSV列 awk -F',' '{print $2,$5}' data.csv
分析日志 awk '/ERROR/ {print $1,$5}' app.log
文本统计 awk '{chars+=length($0);words+=NF} END{print "Chars:",chars,"Words:",words}'
数据转换 awk 'BEGIN{OFS=":"} {$1=$1; print}' file (重新格式化分隔符)
关联多个文件 awk 'NR==FNR{a[$1]=$2;next} {print $0, a[$1]}' file1 file2

✅ ​​最佳实践​​:

  • 处理结构化数据优先使用awk而非grep/sed
  • 复杂任务用BEGIN预处理和END汇总
  • 避免修改源文件,输出到新文件:awk '...' input > output

⚠️ ​​注意​​:

  1. $0$1等变量不用$前缀(print $1正确,print {$1}错误)
  2. 数值计算需确保字段是数字(非数字会当作0)

 四、关于grep与find命令的区别

简单来讲,find主要查找文件,而grep主要查找文件内容

特性​ grep find
​目标​ 文件​​内容​ 文件/目录​​自身属性​
​主要功能​ 文本模式匹配 按条件查找文件/目录
​递归搜索​ 需 -r 选项(如 grep -r 天生递归(从指定目录开始)
​结合正则​ 默认支持正则表达式 仅 -name 支持基础通配符(需用 -regex 支持完整正则)

find(文件查找工具)​

  • ​用途​​:在​​目录树​​中查找符合条件(名称、大小、时间等)的​​文件/目录​​。
  • ​工作对象​​:文件/目录的元数据(如文件名、大小、修改时间)。
  • ​常用选项​​:
    • -name:按文件名搜索(如 find . -name "*.jpg")。
    • -type:按类型搜索(f=文件,d=目录)。
    • -size:按文件大小搜索(如 find / -size +100M 找大于100MB的文件)。
    • -mtime:按修改时间搜索(如 find ~ -mtime -7 找7天内修改的文件)。
    • -exec:对搜索结果执行命令(如 find . -name "*.tmp" -exec rm {} \;)。
  • ​示例​​:
    # 查找 /home 下所有 .txt 文件
    find /home -type f -name "*.txt"
    
    # 删除 /tmp 中 30 天前修改的 .log 文件
    find /tmp -name "*.log" -mtime +30 -delete

    所以在实际使用时,一般先使用find查找到文件,然后使用grep对文件内容进行操作。

 


网站公告

今日签到

点亮在社区的每一天
去签到