grep、sed、awk三剑客

前言

在Linux世界中,有三把强大的文本处理工具,它们被称为”三剑客”:grep、sed和awk。这些工具是Linux系统管理员和开发者的必备技能,它们能够高效地处理文本数据,进行复杂的文本搜索、替换和报告生成等任务。

grep —— 文本过滤

挖坑待填

sed —— 文本修改

介绍:sed 是流编辑器,用于对文本进行处理和转换。它可以按行处理文本,并支持使用正则表达式进行匹配和替换。

用法:sed 命令通常用于对文件内容进行替换、删除、插入等操作。

挖坑待填

awk —— 文本处理

介绍:awk 是一种强大的文本处理工具,用于按行处理和分析文本数据。它支持处理字段(列)数据,并提供灵活的条件语句和循环结构。

用法:awk 命令通常用于从文本中提取指定字段、计算数据等操作。

基本用法

awk的基本用法就是下面的形式。

1
2
3
4
5
# 格式
$ awk 动作 文件名

# 示例
$ awk '{print $0}' demo.txt

单引号中有一对中括号,里面就是每一行的处理操作。其中,print是打印命令,$0代表当前行。

因此上面命令的执行结果,就是把每一行原样打印出来。

常用选项

  • -F:设置输入字段的分隔符。
  • -v:向awk脚本传递变量。
-F

对于/etc/passwd文件,我们可以使用代码将它第一段的用户名进行输出

1
2
3
4
5
6
7
8
$ awk -F ':' '{ print $1 }' demo.txt
# 还可以-F: 照样生效
root
daemon
bin
sys
sync

使用-F参数,将这个文件的字段分隔符指定为:,再使用$1输出第一段内容

如果不-F指定,awk会默认根据空格和制表符(tab),将每一行分成若干字段

-v

-v:向awk脚本传递变量。

1
$ awk -v var="value" '{print var}'  # 使用外部变量

执行流程

awk运行处理规则的执行流程,依次排序

  1. BEGIN{}: 最开始执行
  2. //: 正则
  3. {}: 循环体
  4. END{}: 最后执行

awk语句中最少有一个,最多有四个!

内置变量

在 awk 中有许多内置变量,这些变量提供了关于当前处理行和字段的信息,可以帮助你更方便地对数据进行处理和分析。以下是一些常用的 awk 内置变量:

  • NF:表示当前行的字段(列)数。

  • NR:表示当前记录(行)的行号。

  • $0:表示整个当前行的内容。

  • $1, $2, $3, …:表示当前行的第 1、2、3 个字段的内容,以此类推。

  • FS:输入字段分隔符(默认为空格或制表符)。

  • OFS:输出字段分隔符(默认为空格)。

  • RS:输入记录分隔符(默认为换行符)。

  • ORS:指定输出记录分隔符(默认为换行符)。

  • FILENAME:当前输入文件的文件名。

  • FNR:当前文件中的记录号(针对多个文件处理时的行号,从 1 开始)。

  • ARGC:命令行参数的数量。

  • ARGV:一个数组,包含命令行参数的值。

  • BEGIN{FS=":"}:相当于指定以 : 为分隔符

    FS的优先级要高于 -F

例子:

1
2
3
4
5
$ awk -F: 'BEGIN{OFS=" >>> "}{print $NF, $1}' /etc/passwd
/bin/bash >>> root
/sbin/nologin >>> bin
/sbin/nologin >>> daemon
...

BEGIN{OFS=" >>> "}:指定打印分隔符

$NF:存储以 >>> 分隔符的最后一列

$1:存储以 >>> 分隔符的第一列

print:打印

函数

awk还提供了一些内置函数,方便对原始数据的处理。

  • toupper()将函数中的字符转为大写。

  • tolower():将函数中的字符转为小写。

  • length():返回函数中的字符串长度。

  • substr():返回函数中的子字符串。

  • sin():正弦。

  • cos():余弦。

  • sqrt():平方根。

  • rand():随机数。

  • index():搜索一个字符串内是否包含另一个子字符串

    • 如果找到子字符串,则返回子字符串在搜索字符串中第一次出现的位置。
    • 如果未找到子字符串,则返回 0。
    1
    2
    $ index(str, substr [, start_position])
    # start_position:搜索的起始位置,默认从搜索字符串的第一个字符开始(位置 1)。

/etc/passwd的第一段字符和一行的长度输出,中间添加---优化输出可读性

1
2
3
4
5
6
$ cat /etc/passwd | awk -F ':' '{print toupper($1),"---", length($0) }'
# 还可以-F: 照样生效
ROOT --- 31
BIN --- 32
DAEMON --- 39
...

awk内置函数的完整列表,可以查看手册

条件表达式 / 正则

awk允许指定输出条件,只输出符合条件的行。

格式为:awk '条件 动作' 文件名

  • == 等于
  • > 大于
  • >= 大于等于
  • < 小于
  • <= 小于等于
  • ~ 正则匹配(包含)
  • !~ 正则匹配(不包含)

输出包含root的行

1
2
3
4
$ awk '/root/ {print $0}' /etc/passwd 
root:x:0:0:root:/root:/bin/bash
operator:x:11:0:operator:/root:/sbin/nologin
# awk中先执行正则,再执行循环,匹配文件内有root的每一行。

输出结尾包含bash的行

1
2
$ awk -F: '$NF ~ /bash/{print $0}' /etc/passwd
# 还可以-F: 照样生效

输出结尾不包含bash的行

1
2
$ awk -F '$NF !~ /bash/{print $0}' /etc/passwd
# 还可以-F: 照样生效

匹配root开头的行

1
$ awk '/^root/{print $0}' /etc/passwd

算数表达式

  • +
  • -
  • *
  • /
  • % 求余

输出奇偶数行,NR表示当前行

1
2
3
4
5
6
$ awk -F ':' 'NR % 2 == 1 {print $1}' /etc/passwd
# 还可以-F: 照样生效
root
daemon
lp
...

逻辑表达式

  • &&:逻辑与操作符,确保同时满足上述两个条件。
  • ||:逻辑或操作符,确保只需满足上述一个条件。

输出指定区间行数的行

1
2
3
$ awk 'NR>1 && NR<=3 {print $0}' /etc/passwd
bin:x:1:1:bin:/bin:/sbin/nologin
daemon:x:2:2:daemon:/sbin:/sbin/nologin

流程控制

if

{}循环体中使用,有 不使用中括号 和 使用中括号 的两种格式

  • if() ;else if() ;else{}
  • if(){}else if(){}else{}

例子:输出第一段有root的第一字段和最后一字段

不使用中括号:

1
2
3
4
5
# if
$ awk -F ':' '{if ($1 == "root") print $1,$NF;}' /etc/passwd
# else
$ awk -F ':' '{if ($1 == "root") print $1,$NF; else print "---"}' /etc/passwd
# 不使用中括号/花括号的if语句,在双分支、多分支时必须要使用;分号

使用中括号:

1
2
3
4
# if
$ awk 'BEGIN{FS=":"} {if ($1 == "root"){print $1,$NF}}' /etc/passwd
# else
$ awk 'BEGIN{FS=":"} {if ($1 == "root"){print $1,$NF}else{print "---"}}' /etc/passwd

使用多个内置变量,也是用;分号

1
2
$ awk 'BEGIN{FS=":";OFS=" >>> "} {if ($1 == "root"){print $1,$NF}}' /etc/passwd
root >>> /bin/bash

如果输入行包含 “root”,则打印第一个字段。

1
$ echo "user: root" | awk '{ if (index($0, "root") > 0) print $1 }'

for

{}循环体中使用,格式为:for(variable="变量初始值":条件判断:更新循环控制变量){}

例子:每一行打印10次

1
$ awk -F: '{for(i=10;i>0;i--){print $0}}' /etc/passwd

while

{}循环体中使用,格式为:while(条件判断){}

例子:while每一行打印10次

1
$ awk -F: '{i=1; while(i<10){print $0, i++}}' /etc/passwd

grep、sed、awk三剑客
https://www.fishingrodd.cn/2024/08/25/grepsedawk三剑客/
作者
FishingRod
发布于
2024年8月25日
许可协议