Shell三剑客awk,sed,grep使用教程

简介

Linux 上有三个命令行工具用来处理数据,分别是grepsedawk,通常它们被称为 Shell 三剑客(或文本处理三剑客)。 它们是 Unix/Linux 系统中非常强大且常用的文本处理工具,各自擅长不同的任务:

  • grep: 主要用于查找文本,根据模式(pattern)匹配行,并输出匹配的行。

  • sed: 主要用于编辑文本,可以进行替换、删除、插入、追加等操作。它是一个流编辑器,逐行处理文本。

  • awk: 主要用于分析和处理文本,可以将文本分割成字段,并对字段进行各种操作,例如计算、格式化输出等。它是一种编程语言,可以编写复杂的脚本。

这三个工具经常一起使用,构成强大的文本处理流水线。 例如,可以使用 grep 查找包含特定模式的行,然后使用 sed 对这些行进行编辑,最后使用 awk 对编辑后的结果进行分析和格式化输出。

grep

这是一个命令行搜索工具,可以在文件或输入流中搜索特定模式的行

结合管道命令将执行的结果传递给后面,对于完成一些复杂的操作很友好 好的,以下是 grep 的基本语法和常用选项:

基本结构

1
grep [OPTIONS] PATTERN [FILE...]
  • grep: 调用 grep 命令。
  • [OPTIONS]: 可选的选项,用于修改 grep 的行为。
  • PATTERN: 要搜索的模式,通常是一个字符串或正则表达式。
  • [FILE...]: 要搜索的文件名。可以指定多个文件,如果省略,则 grep 从标准输入读取数据。

常用选项

  • -i (或 --ignore-case): 忽略大小写。
  • -v (或 --invert-match): 反向匹配,只显示不匹配 PATTERN 的行。
  • -n (或 --line-number): 显示匹配行的行号。
  • -c (或 --count): 只显示匹配行的数量,而不是匹配的行本身。
  • -l (或 --files-with-matches): 只显示包含匹配行的文件名,而不显示匹配的行本身。
  • -L (或 --files-without-match): 只显示不包含匹配行的文件名。
  • -r (或 -R--recursive): 递归搜索目录下的所有文件。
  • -h (或 --no-filename): 在输出中不显示文件名。 当搜索多个文件时,默认会显示文件名。
  • -H (或 --with-filename): 在输出中显示文件名。 这是默认行为,但可以用来覆盖 -h 选项。
  • -w (或 --word-regexp): 只匹配完整的单词。
  • -x (或 --line-regexp): 只匹配整行都匹配的情况。
  • -o (或 --only-matching): 只显示匹配的部分,而不是整行。
  • -q (或 --quiet--silent): 静默模式,不输出任何信息,只返回退出状态码(0 表示找到匹配,1 表示没有找到匹配)。
  • -s (或 --no-messages): 禁止显示错误消息。
  • -b (或 --byte-offset): 显示匹配行的字节偏移量。
  • -m NUM (或 --max-count=NUM): 在找到 NUM 个匹配行后停止搜索。
  • -A NUM (或 --after-context=NUM): 显示匹配行之后 NUM 行。
  • -B NUM (或 --before-context=NUM): 显示匹配行之前 NUM 行。
  • -C NUM (或 --context=NUM): 显示匹配行之前和之后 NUM 行。
  • -e PATTERN: 指定多个搜索模式。例如,grep -e "pattern1" -e "pattern2" file.txt
  • -f FILE (或 --file=FILE): 从文件中读取搜索模式,每行一个模式。
  • --color[=WHEN]: 高亮显示匹配的部分。WHEN 可以是 alwaysautonever
  • -E (或 --extended-regexp): 使用扩展正则表达式。
  • -F (或 --fixed-strings): 将 PATTERN 解释为固定字符串,而不是正则表达式。
  • -P (或 --perl-regexp): 使用 Perl 兼容的正则表达式(PCRE)。
  • -d ACTION (或 --directories=ACTION): 指定如何处理目录。ACTION 可以是 read (默认)、skiprecurse
  • -exclude=GLOB: 跳过文件名匹配 GLOB 模式的文件或目录。
  • -exclude-dir=DIR: 在递归搜索中,排除 DIR 目录。

模式 (PATTERN)

  • 普通字符串: 例如,grep "hello" file.txt
  • 正则表达式: 例如,grep "^[0-9]" file.txt 匹配以数字开头的行。 grep -E "pattern1|pattern2" file.txt 匹配包含 “pattern1” 或 “pattern2” 的行(使用扩展正则表达式)。

正则表达式中的特殊字符

  • . (点):匹配任意单个字符(除了换行符)。
  • * (星号):匹配前一个字符零次或多次。
  • + (加号):匹配前一个字符一次或多次(需要 -E 选项)。
  • ? (问号):匹配前一个字符零次或一次(需要 -E 选项)。
  • [] (字符类):匹配方括号中的任意一个字符。 例如,[abc] 匹配 “a”、“b” 或 “c”。
  • [^] (否定字符类):匹配不在方括号中的任意一个字符。 例如,[^abc] 匹配除了 “a”、“b” 和 “c” 之外的任意字符。
  • ^ (脱字符):匹配行首。 在字符类中表示否定。
  • $ (美元符号):匹配行尾。
  • \ (反斜杠):转义特殊字符,使其失去特殊含义。 例如,\. 匹配字面上的点字符。
  • \| (管道符):表示或(需要 -E 选项)。 例如,foo\|bar 匹配 “foo” 或 “bar”。
  • () (圆括号):用于分组和捕获匹配的子字符串(需要 -E 选项)。
  • {} (花括号):用于指定匹配次数的范围(需要 -E 选项)。 例如,a{2,4} 匹配 “a” 出现 2 到 4 次。
  • \b:匹配单词边界。
  • \w:匹配单词字符(字母、数字和下划线)。
  • \s:匹配空白字符(空格、制表符等)。
  • \d:匹配数字(某些 grep 版本支持,或者使用 [0-9])。
  • \<:匹配单词的开头(某些 grep 版本支持)。
  • \>:匹配单词的结尾(某些 grep 版本支持)。

退出状态码

  • 0: 找到匹配的行。
  • 1: 没有找到匹配的行。
  • 2: 发生错误。

示例

  • 在文件 file.txt 中搜索包含 “hello” 的行:

    1
    
    grep "hello" file.txt
    
  • 在文件 file.txt 中搜索包含 “hello” 的行,忽略大小写:

    1
    
    grep -i "hello" file.txt
    
  • 在文件 file.txt 中搜索不包含 “hello” 的行:

    1
    
    grep -v "hello" file.txt
    
  • 在文件 file.txt 中搜索以数字开头的行:

    1
    
    grep "^[0-9]" file.txt
    
  • 在文件 file.txt 中搜索以 “hello” 结尾的行:

    1
    
    grep "hello$" file.txt
    
  • 在文件 file.txt 中搜索完整的单词 “hello”:

    1
    
    grep -w "hello" file.txt
    
  • 递归搜索当前目录下所有文件中包含 “hello” 的行:

    1
    
    grep -r "hello" .
    
  • 只显示包含 “hello” 的文件名:

    1
    
    grep -l "hello" *
    
  • 显示匹配行及其行号:

    1
    
    grep -n "hello" file.txt
    
  • 显示匹配行之前的 2 行:

    1
    
    grep -B 2 "hello" file.txt
    
  • 显示匹配行之后的 2 行:

    1
    
    grep -A 2 "hello" file.txt
    
  • 显示匹配行前后各 2 行:

    1
    
    grep -C 2 "hello" file.txt
    
  • 统计包含 “hello” 的行数:

    1
    
    grep -c "hello" file.txt
    
  • 从文件中读取搜索模式:

    1
    
    grep -f patterns.txt file.txt
    
  • 使用扩展正则表达式搜索包含 “foo” 或 “bar” 的行:

    1
    
    grep -E "foo|bar" file.txt
    
  • 管道中使用 grep:

    1
    
    ls -l | grep "file.txt"
    

注意事项

  • grep 默认区分大小写。
  • 如果 PATTERN 包含空格或其他特殊字符,最好用引号括起来。
  • 正则表达式是 grep 的重要组成部分,需要熟练掌握。
  • 不同版本的 grep 在正则表达式的支持上可能有所差异。GNU grep 提供了更强大的正则表达式功能。
  • 使用 Shell 变量:如果想在grep命令中使用 Shell 变量,要使用双引号"",这样 Shell 变量会被展开。 如果使用单引号,则变量不会被展开,而是会被当做普通字符串。
  • grep --help 可以查看 grep 的帮助信息。

sed

sed 是一个文本处理工具,用于在命令行中对文件中的文本进行修改。它的输入可以是文件,也可以从管道读取数据

基本结构

1
2
3
sed 'command' 文件名
sed -e 'command1' -e 'command2' ... 文件名
sed -f scriptfile 文件名
  • sed: 调用 sed 命令。
  • 'command': 要执行的 sed 命令。 命令用单引号括起来。
  • -e 'command': 允许指定多个命令。
  • -f scriptfile: 从文件中读取命令。
  • 文件名: 要处理的文件名。 如果省略,则 sed 从标准输入读取数据。

常用命令

  • s/regexp/replacement/flags (替换)
    • s: 表示替换命令。
    • regexp: 正则表达式,匹配要替换的内容。
    • replacement: 替换后的内容。
    • flags: 可选的标志:
      • g: 全局替换,替换所有匹配项,而不是只替换第一个。
      • i: 忽略大小写。
      • w 文件名: 将替换结果写入指定的文件。
      • 1, 2, …, 9: 只替换第 N 个匹配项。
  • d (删除):删除行。
  • a text (追加):在当前行之后追加文本。
  • i text (插入):在当前行之前插入文本。
  • c text (更改):将当前行替换为文本。
  • p (打印):打印当前行(通常与 -n 选项一起使用,用于抑制默认输出)。
  • n (下一行):读取下一行,然后执行命令。
  • q (退出):退出 sed。
  • r 文件名 (读取):将指定文件的内容追加到当前行之后。
  • w 文件名 (写入):将匹配的行写入指定的文件。
  • y/source/dest/ (转换):将 source 中的字符转换为 dest 中对应的字符(类似于 tr 命令)。
  • = (行号):打印行号。
  • ! (非):反转选择的含义。 例如,sed '/pattern/!d' file 删除所有不匹配 pattern 的行。
  • { } (分组):将多个命令组合在一起。

地址 (Addresses)

地址用于指定命令作用的行。 地址可以是:

  • 行号: 例如,10 表示第 10 行。
  • $: 最后一行。
  • 正则表达式: 例如,/pattern/ 表示匹配 pattern 的行。
  • 范围:
    • 行号1,行号2: 从行号 1 到行号 2 的范围(包括这两行)。
    • /pattern1/,/pattern2/: 从匹配 pattern1 的行到匹配 pattern2 的行(包括这两行)。
    • 行号,/pattern/: 从指定行号到匹配 pattern 的行。
    • /pattern/,行号: 从匹配 pattern 的行到指定行号。

如果省略地址,则命令作用于所有行。

常用选项

  • -n (安静模式):抑制默认输出(只打印由 p 命令显式打印的行)。
  • -i[SUFFIX] (原地编辑):直接修改文件内容。 SUFFIX 是可选的备份文件名后缀。 例如,sed -i.bak 's/foo/bar/g' file.txt 会将 file.txt 中所有的 “foo” 替换为 “bar”,并将原始文件备份为 file.txt.bak重要提示: 使用 -i 选项要小心,因为这会永久更改文件。 不加 SUFFIX 会直接修改,不做备份,更要小心。
  • -e script (多命令):允许在命令行中指定多个命令。
  • -f scriptfile (脚本文件):从文件中读取命令。
  • -r (扩展正则表达式):使用扩展正则表达式,例如可以使用 +, ?, | 等元字符。 (GNU sed)
  • -E (扩展正则表达式): 与 -r 效果相同,POSIX 标准。(BSD sed, macOS)

示例

  • 将文件 file.txt 中所有的 “foo” 替换为 “bar”,并打印到标准输出:

    1
    
    sed 's/foo/bar/g' file.txt
    
  • 将文件 file.txt 中所有的 “foo” 替换为 “bar”,并直接修改文件:

    1
    
    sed -i 's/foo/bar/g' file.txt
    
  • 将文件 file.txt 中所有的 “foo” 替换为 “bar”,并备份原始文件为 file.txt.bak:

    1
    
    sed -i.bak 's/foo/bar/g' file.txt
    
  • 删除文件 file.txt 中的所有空行:

    1
    
    sed '/^$/d' file.txt
    
  • 打印文件 file.txt 的第 10 行:

    1
    
    sed -n '10p' file.txt
    
  • 打印文件 file.txt 中包含 “error” 的行:

    1
    
    sed -n '/error/p' file.txt
    
  • 删除文件 file.txt 中从包含 “start” 的行到包含 “end” 的行:

    1
    
    sed '/start/,/end/d' file.txt
    
  • 在文件 file.txt 的每一行之后追加 “—”:

    1
    
    sed 'a ---' file.txt
    
  • 将文件 file.txt 中的前 10 行写入 output.txt:

    1
    
    sed '1,10w output.txt' file.txt
    
  • 将文件 file.txt 中的所有小写字母转换为大写字母:

    1
    
    sed 'y/abcdefghijklmnopqrstuvwxyz/ABCDEFGHIJKLMNOPQRSTUVWXYZ/' file.txt
    
  • 删除文件 file.txt 中的注释行(以 # 开头的行):

    1
    
    sed '/^#/d' file.txt
    
  • 使用多个命令将文件 file.txt 中的 “foo” 替换为 “bar”,并将 “hello” 替换为 “world”:

    1
    
    sed -e 's/foo/bar/g' -e 's/hello/world/g' file.txt
    
  • 从脚本文件 script.sed 中读取命令:

    1
    
    sed -f script.sed file.txt
    
  • 仅替换每行中第一次出现的"foo" 为 “bar”

    1
    
    sed 's/foo/bar/' file.txt
    
  • 替换每行中第三次出现的"foo" 为 “bar”

    1
    
    sed 's/foo/bar/3' file.txt
    

正则表达式中的特殊字符

  • . (点):匹配任意单个字符(除了换行符)。
  • * (星号):匹配前一个字符零次或多次。
  • + (加号):匹配前一个字符一次或多次(扩展正则表达式,需要 -r-E 选项)。
  • ? (问号):匹配前一个字符零次或一次(扩展正则表达式,需要 -r-E 选项)。
  • [] (字符类):匹配方括号中的任意一个字符。 例如,[abc] 匹配 “a”、“b” 或 “c”。
  • [^] (否定字符类):匹配不在方括号中的任意一个字符。 例如,[^abc] 匹配除了 “a”、“b” 和 “c” 之外的任意字符。
  • ^ (脱字符):匹配行首。 在字符类中表示否定。
  • $ (美元符号):匹配行尾。
  • \ (反斜杠):转义特殊字符,使其失去特殊含义。 例如,\. 匹配字面上的点字符。
  • \| (管道符):表示或(扩展正则表达式,需要 -r-E 选项)。 例如,foo\|bar 匹配 “foo” 或 “bar”。
  • () (圆括号):用于分组和捕获匹配的子字符串。 捕获的子字符串可以在 replacement 中使用 \1, \2 等引用。
  • {} (花括号):用于指定匹配次数的范围。 例如,a{2,4} 匹配 “a” 出现 2 到 4 次。
  • \b:匹配单词边界。
  • \w:匹配单词字符(字母、数字和下划线)。
  • \s:匹配空白字符(空格、制表符等)。
  • \d:匹配数字。 (某些 sed 版本支持)
  • \<:匹配单词的开头。
  • \>:匹配单词的结尾。

注意事项

  • sed 默认不会修改原始文件,而是将处理结果输出到标准输出。 使用 -i 选项可以修改原始文件。
  • 正则表达式是 sed 的重要组成部分,需要熟练掌握。
  • 使用 -i 选项时要小心,最好先备份文件。
  • 不同版本的 sed 在正则表达式的支持上可能有所差异。 GNU sed 提供了更强大的正则表达式功能。
  • 使用 Shell 变量:如果想在sed命令中使用 Shell 变量,要使用双引号"",这样 Shell 变量会被展开。 如果使用单引号,则变量不会被展开,而是会被当做普通字符串。

awk

awk 是一种文本处理工具,主要用于从文本文件中提取数据并进行格式化输出。 它是一种编程语言,允许你编写脚本来处理文本数据。 awk 逐行读取输入文件,将每一行分割成字段,然后根据你定义的规则对这些字段进行处理。 好的,以下是 awk 的基本语法和常用特性:

基本结构

1
awk 'pattern { action }' file(s)
  • awk: 调用 awk 命令。
  • 'pattern { action }': 这是 awk 的程序,用单引号括起来。
    • pattern: 一个条件表达式(可选)。 如果省略,则对每一行都执行 actionpattern 可以是:
      • 正则表达式: /regex/
      • 比较表达式: NR == 2, $1 > 10
      • 范围模式: /start/, /end/
      • 组合模式: pattern1 && pattern2, pattern1 || pattern2, !pattern
    • { action }: 要执行的动作。 action 可以包含一个或多个语句,用分号分隔。 如果省略,则默认动作为 print $0 (打印整行)。
  • file(s): 要处理的一个或多个文件名(可选)。 如果省略,则 awk 从标准输入读取数据。

动作 (Actions)

一些常用的 actions:

  • print: 打印。
    • print $0: 打印整行。
    • print $1: 打印第一个字段。
    • print $1, $2: 打印第一个和第二个字段,用 OFS 分隔 (默认空格)。
    • print "Hello", $1: 打印字符串 “Hello” 和第一个字段,用 OFS 分隔。
  • printf: 格式化打印,类似于 C 语言的 printf
    • printf "%s %d\n", $1, $2: 打印第一个字段(字符串)和第二个字段(整数),并换行。
  • 赋值: 给变量赋值。
    • count = count + 1
    • name = $1
  • 控制流语句:
    • if (condition) { statements } else { statements }
    • for (i = 1; i <= NF; i++) { statements }
    • while (condition) { statements }
    • do { statements } while (condition)
    • break
    • continue
    • exit
  • next: 跳过当前行,处理下一行。
  • delete array[index]: 删除数组元素。

字段和记录

  • 字段: 每一行被分割成多个字段,默认分隔符是空格或制表符。
    • $1: 第一个字段。
    • $2: 第二个字段。
    • $NF: 最后一个字段 (NF 是字段数)。
    • $0: 整行记录。
  • 记录: 每一行被称为一个记录。
  • FS (Field Separator): 字段分隔符,默认是空格或制表符。 可以用 -F 选项或在 BEGIN 块中设置。
  • RS (Record Separator): 记录分隔符,默认是换行符。
  • OFS (Output Field Separator): 输出字段分隔符,默认是空格。
  • ORS (Output Record Separator): 输出记录分隔符,默认是换行符。
  • NF (Number of Fields): 当前记录的字段数。
  • NR (Number of Records): 当前记录的行号 (从 1 开始)。

模式 (Patterns)

  • 正则表达式:
    • /pattern/: 匹配包含 pattern 的行。
    • $1 ~ /pattern/: 匹配第一个字段包含 pattern 的行。
    • $1 !~ /pattern/: 匹配第一个字段不包含 pattern 的行。
  • 比较表达式:
    • NR == 2: 匹配第二行。
    • $1 > 10: 匹配第一个字段大于 10 的行。
    • $2 == "abc": 匹配第二个字段等于 “abc” 的行。
  • 范围模式:
    • /start/, /end/: 匹配从包含 start 的行到包含 end 的行(包括这两行)。
  • 组合模式:
    • $1 > 10 && $2 < 20: 匹配第一个字段大于 10 并且第二个字段小于 20 的行。
    • $1 == "a" || $2 == "b": 匹配第一个字段等于 “a” 或者第二个字段等于 “b” 的行。
    • !($1 == "c"): 匹配第一个字段不等于 “c” 的行。
  • BEGINEND:
    • BEGIN { actions }: 在处理任何输入之前执行 actions
    • END { actions }: 在处理完所有输入之后执行 actions

变量

  • 内置变量:
    • FS, RS, OFS, ORS, NF, NR (前面已介绍)
    • FILENAME: 当前文件名。
    • FNR: 当前文件中的行号。
    • ARGC: 命令行参数的数量。
    • ARGV: 命令行参数数组。
  • 用户自定义变量: 变量名以字母开头,可以包含字母、数字和下划线。

数组

  • array[index] = value
  • 可以用字符串作为数组索引 (关联数组)。
  • for (index in array) { ... }: 遍历数组。
  • delete array[index]: 删除数组元素。

函数

  • 内置函数:

    • 字符串函数: length(), substr(), index(), split(), tolower(), toupper()
    • 数学函数: sqrt(), sin(), cos(), rand(), srand()
    • 时间函数: systime(), strftime()
  • 用户自定义函数:

    1
    2
    3
    4
    
    function function_name(parameter1, parameter2, ...) {
        statements
        return value  # 可选
    }
    

示例

  • 打印每一行的第一个字段:

    1
    
    awk '{print $1}' file.txt
    
  • 打印第二行:

    1
    
    awk 'NR == 2' file.txt
    
  • 打印所有包含 “error” 的行:

    1
    
    awk '/error/' file.txt
    
  • 打印第一个字段大于 10 的行的第二个字段:

    1
    
    awk '$1 > 10 {print $2}' file.txt
    
  • 统计文件中所有行的字段总数:

    1
    
    awk '{sum += NF} END {print sum}' file.txt
    
  • 使用逗号作为字段分隔符,并打印每行的第一个和第三个字段:

    1
    
    awk -F',' '{print $1, $3}' file.txt
    
  • 在处理文件之前设置字段分隔符,并在处理完文件后打印总行数:

    1
    
    awk 'BEGIN {FS = ","} {print $1} END {print "Total lines:", NR}' file.txt
    
  • 将所有行的第一个字段转换为大写:

    1
    
    awk '{ $1 = toupper($1); print $0 }' file.txt
    

更详细的说明

最后更新于 Jun 24, 2025 10:43 +0800
页面浏览量Loading
网站总访客数:Loading
网站总访问量:Loading
使用 Hugo 构建
主题 StackJimmy 设计
-->