Linux 和 Unix 系统中非常流行文本处理工具awk

awk 是一种强大的文本处理工具,在 Linux 和 Unix 系统中非常流行。它主要用于模式扫描和处理语言,可以读取输入文件、为数据行中的字段指定操作,并基于这些操作输出数据。awk 程序通常由一系列的模式和动作对组成,模式指定了哪些数据行应被处理,而动作则定义了在这些行上应执行的操作。

基本语法

bash 复制代码
awk 'pattern { action }' input_file

用法:awk [options]  '{print NR,$0}' file
-F   指定字段分隔符
NR   表示行号
$0   表示这一行的内容
$1   数字 某一列
$NF  最后一列
  • pattern:是可选的,用于指定哪些行应该被处理。如果省略,则处理所有行。
  • { action }:是必需的,定义了当行匹配模式时应该执行的操作。
  • input_file:指定输入文件名。如果省略,则从标准输入读取数据。

示例

打印所有行
bash 复制代码
awk '{print}' filename

或简单地

bash 复制代码
awk 1 filename

这里,1 被视为总是为真的模式,因此所有行都会被打印。

打印第一列
bash 复制代码
awk '{print $1}' filename

$1 表示第一列。

打印第1~7列

bash 复制代码
[root@localhost ~]# head -10 /etc/passwd | awk -F ":" '{print $1,$2,$3,$4,$5,$6,$7}'
root x 0 0 root /root /bin/bash
bin x 1 1 bin /bin /sbin/nologin
daemon x 2 2 daemon /sbin /sbin/nologin
adm x 3 4 adm /var/adm /sbin/nologin
lp x 4 7 lp /var/spool/lpd /sbin/nologin
sync x 5 0 sync /sbin /bin/sync
shutdown x 6 0 shutdown /sbin /sbin/shutdown
halt x 7 0 halt /sbin /sbin/halt
mail x 8 12 mail /var/spool/mail /sbin/nologin
operator x 11 0 operator /root /sbin/nologin

打印当前记录(即整行)的内容

bash 复制代码
[root@localhost ~]# head -10 /etc/passwd | awk -F ":" '{print $0}'
root:x:0:0:root:/root:/bin/bash
bin:x:1:1:bin:/bin:/sbin/nologin
daemon:x:2:2:daemon:/sbin:/sbin/nologin
adm:x:3:4:adm:/var/adm:/sbin/nologin
lp:x:4:7:lp:/var/spool/lpd:/sbin/nologin
sync:x:5:0:sync:/sbin:/bin/sync
shutdown:x:6:0:shutdown:/sbin:/sbin/shutdown
halt:x:7:0:halt:/sbin:/sbin/halt
mail:x:8:12:mail:/var/spool/mail:/sbin/nologin
operator:x:11:0:operator:/root:/sbin/nologin

整个命令 head -10 /etc/passwd | awk -F ":" '{print 0}' 的效果其实与仅执行 head -10 /etc/passwd 相同,因为 awk 命令在这里并没有对每行文本进行任何实质性的处理(除了指定了字段分隔符,但这个分隔符在 print 0 的上下文中并未被利用)

bash 复制代码
[root@localhost ~]# head -10 /etc/passwd | awk  '{FS=":"}{print $1,$2,$3,$4,$5,$6,$7}'
root:x:0:0:root:/root:/bin/bash      
bin x 1 1 bin /bin /sbin/nologin
daemon x 2 2 daemon /sbin /sbin/nologin
adm x 3 4 adm /var/adm /sbin/nologin
lp x 4 7 lp /var/spool/lpd /sbin/nologin
sync x 5 0 sync /sbin /bin/sync
shutdown x 6 0 shutdown /sbin /sbin/shutdown
halt x 7 0 halt /sbin /sbin/halt
mail x 8 12 mail /var/spool/mail /sbin/nologin
operator x 11 0 operator /root /sbin/nologin

在您提供的命令 head -10 /etc/passwd | awk '{FS=":"}{print $1,$2,$3,$4,$5,$6,$7}' 中,存在一个常见的 awk 使用误区。FS(字段分隔符)应该在处理任何记录之前设置,而不是在每条记录的处理块中单独设置。当您在 {FS=":"} 这样的代码块中设置 FS 时,它实际上对已经读取到当前记录(即行)没有影响,因为 awk 在读取记录时就已经决定了如何根据 FS 分割这条记录。

因此,您的命令实际上不会按预期工作,因为它在尝试打印字段时并没有正确地使用冒号作为字段分隔符。

正确的做法是在 awk 程序开始时就设置 FS,然后处理记录。这里是修改后的命令:

bash 复制代码
head -10 /etc/passwd | awk -F: '{print $1, $2, $3, $4, $5, $6, $7}'

注意,我已经将 -F: 直接传递给了 awk 命令,而不是在 awk 程序内部设置 FS。这样做可以在 awk 读取每行之前就将冒号设置为字段分隔符。

这个命令将输出 /etc/passwd 文件前10行中每行的前七个字段(如果存在的话)。这些字段通常包括用户名、密码占位符(通常是 x,表示密码存储在 /etc/shadow 中)、用户ID(UID)、组ID(GID)、用户全名或注释、家目录和登录Shell。不过,请注意,并非所有用户的记录都会有七个字段,特别是如果用户全名或注释字段为空或不存在时。但是,awk 会按照指定的字段数打印出内容,对于不存在的字段,它会打印空字符串。

对每行的第一个字段求和
bash 复制代码
awk '{sum += $1} END {print sum}' filename

这个命令会遍历文件中的每一行,将第一列的值累加到变量 sum 中,并在处理完所有行后打印总和。

过滤特定行

打印文件中第二列值大于 10 的所有行:

bash 复制代码
awk '$2 > 10 {print}' filename
bash 复制代码
[root@localhost ~]# vi score.txt
Marry   2143 78 84 77
Jack    2321 66 78 45
Tom     2122 48 77 71
Mike    2537 87 97 95
Bob     2415 40 57 62
Bigmao  8899 99 100 98

-- 计算总成绩shell角本
vi cat_call.awk
#!/bin/awk -f
#运行前
BEGIN {
    math = 0
    english = 0
    computer = 0
    printf "NAME    NO.   MATH  ENGLISH  COMPUTER   TOTAL\n"
    printf "---------------------------------------------\n"
}
#运行中
{
    math+=$3
    english+=$4
    computer+=$5
    printf "%-6s %-6s %4d %8d %8d %8d\n", $1, $2, $3,$4,$5, $3+$4+$5
}
#运行后
END {
    printf "---------------------------------------------\n"
    printf "  TOTAL:%10d %8d %8d \n", math, english, computer
    printf "AVERAGE:%10.2f %8.2f %8.2f\n", math/NR, english/NR, computer/NR
}

[root@localhost ~]# awk -f cat_call.awk score.txt
NAME    NO.   MATH  ENGLISH  COMPUTER   TOTAL
---------------------------------------------
Marry  2143     78       84       77      239
Jack   2321     66       78       45      189
Tom    2122     48       77       71      196
Mike   2537     87       97       95      279
Bob    2415     40       57       62      159
Bigmao 8899     99      100       98      297
---------------------------------------------
  TOTAL:       418      493      448 
AVERAGE:     69.67    82.17    74.67
使用 BEGIN 和 END 块
bash 复制代码
awk 'BEGIN {print "Start processing file..."} {print} END {print "File processing complete."}' filename

BEGIN 块在处理任何输入行之前执行,而 END 块在所有输入行处理完毕后执行。

bash 复制代码
[root@localhost ~]# head -10 /etc/passwd | awk  'BEGIN{FS=":";OFS="****"}{print $1,$2,$3,$4,$5,$6,$7}'
root****x****0****0****root****/root****/bin/bash
bin****x****1****1****bin****/bin****/sbin/nologin
daemon****x****2****2****daemon****/sbin****/sbin/nologin
adm****x****3****4****adm****/var/adm****/sbin/nologin
lp****x****4****7****lp****/var/spool/lpd****/sbin/nologin
sync****x****5****0****sync****/sbin****/bin/sync
shutdown****x****6****0****shutdown****/sbin****/sbin/shutdown
halt****x****7****0****halt****/sbin****/sbin/halt
mail****x****8****12****mail****/var/spool/mail****/sbin/nologin
operator****x****11****0****operator****/root****/sbin/nologin

[root@localhost ~]# head -10 /etc/passwd | awk  'BEGIN{FS=":"}{print $NF}'
/bin/bash
/sbin/nologin
/sbin/nologin
/sbin/nologin
/sbin/nologin
/bin/sync
/sbin/shutdown
/sbin/halt
/sbin/nologin
/sbin/nologin
使用外部变量
bash 复制代码
awk -v var=100 '{if ($1 > var) print $0}' filename

这里,-v var=100 定义了一个名为 var 的外部变量,并将其值设置为 100。然后,在 awk 程序内部使用这个变量来比较第一列的值。

进阶用法

awk 还可以进行更复杂的文本处理,如字符串操作、数组使用、自定义函数等。这些功能使得 awk 成为处理文本数据的强大工具。

注意事项

  • 字段默认由空格或制表符分隔。可以通过 -F 选项更改字段分隔符。
  • awk 程序中的 { action } 可以包含多个语句,语句之间用分号分隔。
  • 变量名区分大小写。

awk 的功能远不止于此,通过结合其内置函数和灵活的语法,你可以完成几乎任何文本处理任务。

相关推荐
分布式存储与RustFS12 分钟前
自托管对象存储的三种 TLS 签发:自签、Let‘s Encrypt、内网 CA 的选择与轮换
运维·云原生·开源·对象存储·分布式存储·s3·性能基准
AI智讯中枢19 分钟前
高性能 C++ 实战 (五):perf+FlameGraph 火焰图生产实战,精准定位 CPU / 缓存 / 锁瓶颈,避坑 + 完整实操案例
linux·c++·性能调优·性能分析·perf·flamegraph·火焰图
Li-Yongjun31 分钟前
fuser
运维
William Dawson32 分钟前
kkFileView 内网 ARM 服务器全链路部署:从「找不到 office」到全绿通关(超详细排障实录)
运维·服务器
海宇数据1 小时前
零信任架构实战:基于海宇车型识别精准构建自动化违章处理网关
运维·人工智能·架构·自动化
xbzb1 小时前
Linux SELinux 安全加固与标签排错手册
linux·运维·安全
其实防守也摸鱼1 小时前
SQL注入实验笔记
android·运维·数据库·安全·oracle·自动化
江屿风1 小时前
【Linux系统】【从【收尾】缓冲区到【新开】磁盘块:一节课打通文件系统底层原理】流食般投喂
linux·运维·服务器·人工智能·笔记
Pointer Pursuit1 小时前
编辑器Vim
linux·编辑器·vim
_upupup2 小时前
Linux中的权限解析
linux·服务器