Linux 文本处理三剑客 ,grep ,sed,awk。Grep是文本过滤工具,sed文本行编辑器,前两者我们已经在前面的博客中做出了介绍,今天介绍awk,awk是一种报表生成器,也就是对文件进行格式化处理,这里的格式化不是文件系统的格式化,而是对文件内容进行各种“排版”,进行格式化显示

在linux上我们使用的是GUN awk简称gawk,gawk是一种过程式编程语言。既然是一种语言那么他就支持条件判断,数组,循环等各种编程语言中所有可以使用的功能,我们可以把gawk称为一种脚本语音解释器。

简单的awk

[root@localhost ~]#awk '{ print }' /etc/passwd

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

..............

liang:x:1004:1004::/home/liang:/bin/bash
zhaoyun:x:1005:1005::/home/zhaoyun:/bin/bash

[root@localhost ~]# awk '{ print }' /etc/passwd|wc -l
48
[root@localhost ~]# cat /etc/passwd |wc -l
48

/etc/passwd 文件的内容出现在眼前。现在,解释 awk 做了些什么。调用 awk 时,我们指定 /etc/passwd 作为输入文件。执行 awk 时,它依次对 /etc/passwd 中的每一行执行 print 命令。所有输出都发送到 stdout,所得到的结果与与执行cat /etc/passwd完全相同。

现在,解释 { print } 代码块。在 awk 中,花括号用于将几块代码组合到一起,这一点类似于 C 语言。在代码块中只有一条 print 命令。在 awk 中,如果只出现 print 命令,那么将打印当前行的全部内容。

另一个 awk 示例,它的作用与上例完全相同

[root@localhost ~]# awk '{ print $0 }' /etc/passwd

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

..............

liang:x:1004:1004::/home/liang:/bin/bash
zhaoyun:x:1005:1005::/home/zhaoyun:/bin/bash

在 awk 中,$0 变量表示整个当前行,所以 print 和 print $0 的作用完全一样。同时我们从前两个例子中也可以看出awk和sed一样是一行一行处理数据的,对于awk来说每一行内容是一个数据。

如果您愿意,可以创建一个 awk 程序,让它输出与输入数据完全无关的数据。以下是一个示例

[root@localhost ~]# awk '{ print "" }' /etc/passwd

...

[root@localhost ~]# awk '{ print "" }' /etc/passwd|wc -l
48

只要将 "" 字符串传递给 print 命令,它就会打印空白行。如果测试该脚本,将会发现对于 /etc/passwd 文件中的每一行,awk 都输出一个空白行。再次说明, awk 对输入文件中的每一行都执行这个脚本。以下是另一个示例

[root@localhost ~]# awk '{ print "hi" }' /etc/passwd
hi
hi
hi
hi

....

hi

[root@localhost ~]# awk '{ print "hi" }' /etc/passwd|wc -l
48

awk 工作原理

  1. awk 使用一行作为输入(通过文件或者管道),并将这一行赋给内部变量 $0

  2. 行被空格分解为字段(单词),每一个字段存储在已编号的变量中,从 $1 开始。( awk 的内部变量 FS 用来确定字段的分隔符。初始时,为空格,包含制表符和空格符)

  3. 对于一行,按照给定的正则表达式的顺序进行匹配,如果匹配则执行对应的 Action ,如果没有匹配上则不执行任何动作 , Search Pattern 和 Action 是可选的,但是必须提供其中一个 。如果 Search Pattern 未提供,则对所有的输入行执行 Action 操作。如果 Action 未提供,则默认打印出该行的数据 。 {} 这种 Action 不做任何事情,和未提供的 Action 的工作方式不一样

  4. 打印字段,用 print 、 printf 、 sprintf ,格式: { print $1, $3 } 内部变量 output field separator ( OFS ),默认为空格, $n 之间的逗号被 OFS 中的字符替换。

  5. 输出之后,从文件中另取一行,并将其复制到 $0 中,覆盖原来的内容。重复进行……

Print与printf

print 函数用于打印不需要特别编排格式的简单输出。更为复杂的格式编排则要使用 printf 和 sprintf 。若懂得 C 语言,则也一定懂得如何使用 printf 和 sprintf 。

print 函数的的转义序列

  /b 退格

  /f 换页

  /n 换行

  /r 回车

  /t 制表符

  /047 八进制值 47 ,即单引号

  /c c 代表任意其他字符

打印数字时,可能需要控制数字的格式。可以通过 printf 来实现,但是通过设置一个特殊的变量 OFMT ,是用 print 函数也可以控制数字打印格式。 OFMT 默认为“ %.6gd” ,表示只打印小数部分的前 6 位。

[root@localhost ~]# awk 'BEGIN { OFMT="%.2f"; print 1.2456789, 1.234-2 }'
1.25 -0.77

[root@localhost ~]# awk 'BEGIN { printf "%.2f %.2f\n" ,1.2456789, 1.234-2 }'

1.25 -0.77

printf 函数

printf 函数返回一个带格式的字符串给标准输出,如同 C 语言中的 printf 语句。 printf 语句包括一个加引号的控制串,控制串中可能嵌套有若干格式说明和修饰符。控制串后面跟逗号,之后是一列由逗号分隔的表达式。与 print 函数不同的是, printf 函数不会在行尾自动换行。若要换行,在控制串中提供转义字符 /n 。每个百分号和格式说明都必须有一个对应的变量 。要打印百分号就必须在控制串中给出两个百分号。

  printf 函数的转义字符

    c  字符

    s  字符串

    d  十进制整数

    ld 十进制长整数

    u  十进制无符号整数

    lu 十进制无符号长整数

    x  十六进制整数

    lx 十六进制长整数

    o  八进制整数

    lo 八进制长整数

    e  用科学计数法表示浮点数

    f  浮点数

    g  选用 e 或 f 中较短的一种形式

  printf 函数的修饰符

    - 左对齐修饰符

    # 显示八进制整数时,前面加 0 ,显示十六进制整数时,前面加 0x

    + 显示使用 d 、 e 、 f 、 g 转换的整数时,加上正负号

    0 用 0 而不是空白符来填充所显示的值

printf 函数控制串里的管道符(竖杠)是文本的一部分,用于指示格式的起始与结束。

|[root@localhost ~]#echo "UNIX" | awk ' { printf "|%-15s|\n", $11 }'      #%15s表示15个字符的字符串若没有则用空格代替
|UNIX      |
[root@localhost ~]# echo "UNIX" | awk ' { printf "|%-15s\n|", $1 }'
|UNIX
|[root@localhost ~]#

BEGIN与END

通常,对于每个输入行, awk 都会执行每个脚本代码块一次。然而,在许多编程情况中,可能需要在 awk 开始处理输入文件中的文本之前执行初始化代码。对于这种情况, awk 允许您定义一个 BEGIN 块。

因为 awk 在开始处理输入文件之前会执行 BEGIN 块,因此它是初始化 FS(字段分隔符)变量、打印页眉或初始化其它在程序中以后会引用的全局变量的极佳位置。

awk 还提供了另一个特殊块,叫作 END 块。 awk 在处理了输入文件中的所有行之后执行这个块。通常, END 块用于执行最终计算或打印应该出现在输出流结尾的摘要信息。

有一点要明确就是BEGIN{}与END{}仅且只执行一次

[root@localhost ~]# awk 'BEGIN {print 1}{print 2}END{print 3}' /etc/passwd
1
2
2
2
...
2
3

Awk运算符

算术操作符:

x+y, x-y, x*y, x/y, x^y, x%y

-x: 转换为负数

+x: 转换为数值

字符串操作符:没有符号的操作符,字符串连接

赋值操作符:

=, +=, -=, *=, /=, %=, ^=

++, --

比较操作符:

==, !=, >, >=, <, <=

模式匹配符:~:左边是否和右边匹配包含!~:是否不匹配

[root@localhost ~]#awk –F: '$0 ~ /root/{print $1}' /etc/passwdrootoperator[root@localhost ~]#awk –F: '$3==0' /etc/passwdroot:x:0:0:root:/root:/bin/bash

逻辑操作符:与&&,或||,非!

示例:

[root@localhost ~]# awk -F: '$3>=0 && $3<=1000 {print $1}' /etc/passwd
root
bin
daemon
adm
lp

......

liang
zhaoyun

[root@localhost ~]# awk -F: '$3==0 || $3>=1000 {print $1}' /etc/passwd
root
nfsnobody
centos
zhangsan
lisi
li
liang
zhaoyun

[root@localhost ~]# awk -F: '!($3==0) {print $1}' /etc/passwd
bin
daemon
adm
lp
sync
shutdown

.....

liang
zhaoyun

[root@localhost ~]# awk -F: '!($3>=500){print $3}' /etc/passwd
0
1
2
3
4
5
6
7
8
...
74
70
89
72

条件表达式(三目表达式):

selector?if-true-expression:if-false-expression

示例:

[root@localhost ~]# awk -F: '{$3>=1000?usertype="Common User":usertype="Sysadmin or SysUser";printf"%15s:%-s\n",$1,usertype}' /etc/passwd
root:Sysadmin or SysUser
bin:Sysadmin or SysUser
daemon:Sysadmin or SysUser
adm:Sysadmin or SysUser
lp:Sysadmin or SysUser
sync:Sysadmin or SysUser
shutdown:Sysadmin or SysUser
halt:Sysadmin or SysUser
mail:Sysadmin or SysUser
operator:Sysadmin or SysUser
games:Sysadmin or SysUser
ftp:Sysadmin or SysUser
nobody:Sysadmin or SysUser
systemd-network:Sysadmin or SysUser
dbus:Sysadmin or SysUser
polkitd:Sysadmin or SysUser
sssd:Sysadmin or SysUser
libstoragemgmt:Sysadmin or SysUser
rpc:Sysadmin or SysUser
colord:Sysadmin or SysUser
gluster:Sysadmin or SysUser
saslauth:Sysadmin or SysUser
abrt:Sysadmin or SysUser
setroubleshoot:Sysadmin or SysUser
rtkit:Sysadmin or SysUser
pulse:Sysadmin or SysUser
chrony:Sysadmin or SysUser
rpcuser:Sysadmin or SysUser
nfsnobody:Common User
unbound:Sysadmin or SysUser
tss:Sysadmin or SysUser
usbmuxd:Sysadmin or SysUser
geoclue:Sysadmin or SysUser
radvd:Sysadmin or SysUser
qemu:Sysadmin or SysUser
ntp:Sysadmin or SysUser
gdm:Sysadmin or SysUser
gnome-initial-setup:Sysadmin or SysUser
sshd:Sysadmin or SysUser
avahi:Sysadmin or SysUser
postfix:Sysadmin or SysUser
tcpdump:Sysadmin or SysUser
centos:Common User
zhangsan:Common User
lisi:Common User
li:Common User
liang:Common User
zhaoyun:Common User

Awk变量及

自定义变量(区分字符大小写)
  (1) -v var=value
  (2) 在program中直接定义
示例:

[root@localhost ~]# awk -v test='hello gawk' '{print test}' /etc/fstab
hello gawk
hello gawk
hello gawk
hello gawk
hello gawk
hello gawk
hello gawk
hello gawk
hello gawk
hello gawk
hello gawk
hello gawk

[root@localhost ~]# awk -v test='hello gawk' 'BEGIN{print test}'

hello gawk

                                  awk中常见内置变量

变量名 属性
FS 输入字段分隔符,默认为空白字符
OFS 输出字段分隔符,默认为空白字符
RS 输入记录分隔符,指定输入时的换行符
ORS 输出记录分隔符,输出时用指定符号代替换行
NF 字段数量
NR 行号
FNR 各文件分别计数,行号
FILENAME 当前文件名
ARGC 命令行参数的个数
ARGV 数组,保存的是命令行所给定的各参数

Awk 的If,循环,与数组

If

语法:

  if(condition){statement;…}[else statement]
  if(condition1){statement1}else if(condition2){statement2}
  else{statement3}
使用场景:

  对awk取得的整行或某个字段做条件判断
示例:

[root@localhost ~]# awk -F: '{if($3>=1000)print $1,$3}' /etc/passwd
nfsnobody 65534
centos 1000
zhangsan 1001
lisi 1002
li 1003
liang 1004
zhaoyun 1005

[root@localhost ~]# awk -F: '{if($NF=="/bin/bash") print $1}' /etc/passwd
root
centos
zhangsan
lisi
li
liang
zhaoyun

While

语法:

  while(condition){statement;…}
  条件“真”,进入循环;条件“假”,退出循环
使用场景:
  对一行内的多个字段逐一类似处理时使用
  对数组中的各元素逐一处理时使用
示例:

[root@localhost ~]# awk '/^[[:space:]]*linux16/{i=1;while(i<=NF){print $i,length($i); i++}}' /etc/grub2.cfg
linux16 7
/vmlinuz-3.10.0-862.el7.x86_64 30
root=UUID=0c69d6ed-c758-4a3d-a73b-dbcfaca2d817 46
ro 2
crashkernel=auto 16
rhgb 4
quiet 5
LANG=zh_CN.UTF-8 16
linux16 7
/vmlinuz-0-rescue-e650feaecc624ac7ac2823eaad4cf6ca 50
root=UUID=0c69d6ed-c758-4a3d-a73b-dbcfaca2d817 46
ro 2
crashkernel=auto 16
rhgb 4
quiet 5

For

语法:

  for(expr1;expr2;expr3) {statement;…}
常见用法:
  for(variable assignment;condition;iterationprocess)
  {for-body}
特殊用法:

  能够遍历数组中的元素
语法:

  for(varin array) {for-body}
示例:

[root@localhost ~]# awk '/^[[:space:]]*linux16/{for(i=1;i<=NF;i++) {print $i,length($i)}}' /etc/grub2.cfg
linux16 7
/vmlinuz-3.10.0-862.el7.x86_64 30
root=UUID=0c69d6ed-c758-4a3d-a73b-dbcfaca2d817 46
ro 2
crashkernel=auto 16
rhgb 4
quiet 5
LANG=zh_CN.UTF-8 16
linux16 7
/vmlinuz-0-rescue-e650feaecc624ac7ac2823eaad4cf6ca 50
root=UUID=0c69d6ed-c758-4a3d-a73b-dbcfaca2d817 46
ro 2
crashkernel=auto 16
rhgb 4
quiet 5

同样在awk中同样支持break与countinue

[root@localhost ~]# awk -F: '{if($3%2!=0) next; print $1,$3}' /etc/passwd
root 0
daemon 2
lp 4
shutdown 6
mail 8
games 12
ftp 14
systemd-network 192
sssd 998
rpc 32
colord 996
saslauth 994
rtkit 172
chrony 992
nfsnobody 65534
geoclue 990
ntp 38
gdm 42
sshd 74
avahi 70
tcpdump 72
centos 1000
lisi 1002
liang 1004

数组

数组在 awk 中被称为关联数组 ( associative arrays ),其下表既可以是字符串也可以是数字。数组的键和值都存储在 awk 程序内部的一个表中,该表采用的是 散列算法,所以数组元素不是顺序存储的。数组也是被用到时才被创建。 awk 还能判定数组用于保存数字还是字符串,根据上下文被初始化为 0 或者空字符串。数组大小不需要声明。

当下标为字符串或者非连续的数字时,不能用 for 循环来遍历数组。这是就要使用特殊的 for 循环。

[root@localhost ~]# cat test
4234 Tom 43
4571 Tom 22
3298 Eliza 21
4622 Tom 53
2345 Mary 24

[root@localhost ~]# awk '{count[$2]++};END{for(name in count)printf"%s %s\n" ,name,count[name]}' test
Tom 3
Eliza 1
Mary 1

Awk常用的内部函数

数值处理:

  rand():返回0和1之间一个随机数
  

[root@localhost ~]# awk 'BEGIN{srand(); for (i=1;i<=10;i++)print int(rand()*100) }'
98
82
85
18
32
18
40
98
63
80

字符串处理:

  length([s]):返回指定字符串的长度
  sub(r,s,[t]):对t字符串进行搜索r表示的模式匹配的内容,并将第一个匹配的内容替换为s

[root@localhost ~]# echo "2008:08:08 08:08:08" |awk 'sub(/:/,"-",$1)'
2008-08:08 08:0808

  gsub(r,s,[t]):对t字符串进行搜索r表示的模式匹配的内容,并全部替换为s所表示的内容

[root@localhost ~]# echo "2008:08:08 08:08:08" | awk 'gsub(/:/,"-",$0) '
2008-08-08 08-08-08

  split(s,array,[r]):以r为分隔符,切割字符串s,并将切割后的结果保存至array所表示的数组中,第一个索引值为1,第二个索引值为2,…

[root@localhost ~]# netstat -tan | awk '/^tcp\>/{split($5,ip,":");count[ip[1]]++};END{for (i in count) {print i,count[i]}}'
192.168.75.1 1
0.0.0.0 6

Awk中调用shell命令

system命令
空格是awk中的字符串连接符,如果system中需要使用awk中的变量可以使用空格分隔,或者说除了awk的变量外其他一律用""引用起来。

[root@localhost ~]# awk BEGIN'{system("hostname") }'
localhost.localdomain

[root@localhost ~]# awk 'BEGIN{score=100; system("echo your score is " score) }'
your score is 100

转载于:https://www.cnblogs.com/angge/p/9548147.html

Linux入门——文本处理三剑客之gnu awk相关推荐

  1. 五分钟入门文本处理三剑客grep awk sed

    点击上方 好好学java ,选择 星标 公众号 重磅资讯.干货,第一时间送达 今日推荐:Spring Boot + Vue 如此强大?竟然可以开发基于 C/S 架构的应用个人原创+1博客:点击前往,查 ...

  2. awk处理带有空格的字符串_五分钟入门文本处理三剑客grep awk sed

    介绍 grep awk sed是Linux下文本处理常用的命令,能完成很多神奇的操作,今天就分享一下这三个命令最常见的用法 grep 使用一般有如下两种形式 第一种形式 grep [option] [ ...

  3. Linux常用基本命令:三剑客命令之-awk内置函数用法

    awk的内置函数大致可以分类为算数函数.字符串函数.时间函数.其他函数等 算数函数 最常用的算数函数有rand函数.srand函数.int函数. 可以使用rand函数生成随机数,但是使用rand函数时 ...

  4. Linux常用基本命令:三剑客命令之-awk输入输出分隔符

    输入分隔符,英文原文为field separator,此处简称为FS,默认是空白字符(即空格),awk默认以空白字符为分隔符对每一行进行分割. 输出分割符,英文原文为output field sepa ...

  5. linux中文本处理三剑客

    正则表达式(Regular Expression,): 元字符: . 任意单个字符 表示字符个数的元字符: * 匹配其前面的字符任意次 如:a*b 则b,ab aab aaab都可以 但acb不可以 ...

  6. linux常用文本编缉命令(strings/sed/awk/cut/uniq/sort)

    一.strings strings--读出文件中的所有字符串 二.sed--文本编缉 类型 命令 命令说明 字符串替换 sed -i 's/str_reg/str_rep/' filename 将文件 ...

  7. GNU awk 的用法-文本处理三剑客之一

    GNU awk 的用法 awk 简介 文本处理三剑客 awk 工作原理 awk 用法 1.print 2.变量 2.1 内建变量 2.2 自定义变量 3.printf 命令 4.操作符 4.1 算术操 ...

  8. linux生产文本处理掌握这些就够了:awk,gawk,sed,grep,sort

    shell脚本最常见的一个用途就是处理文本文件.检查日志文件.读取配置 文件.处理数据元素,shell脚本可以帮助我们将文本文件中各种数据的日常处理任务自动化.但仅靠shell脚本命令来处理文本文件的 ...

  9. Linux文本处理三剑客之sed

    推荐新手阅读[酷壳]或[骏马金龙]开篇的教程作为入门.骏马兄后面的文章以及官方英文文档较难. [酷壳]:https://coolshell.cn/articles/9104.html [骏马金龙-博客 ...

  10. Linux文本处理三剑客

    grep awk sed是Linux下文本处理常用的命令,这篇笔记就是详细阐述文本三剑客的用法. 功能概述: 概述 grep:文本过滤器,仅仅是过滤文本,没有编辑功能 sed:Stream EDito ...

最新文章

  1. 再见吧,996!程序员开源考公指南获高赞:三人已成功上岸
  2. 数值分区间_EXCEL统计区间个数的专属函数
  3. WinForm经典窗体皮肤[重绘]
  4. RxJava的初步认识
  5. pdfdom将pdf转成html,使用pdfdom将pdf转为html(示例代码)
  6. C1083: 无法打开包括文件: “stdafx.h”: No such file or directory
  7. MySQL时间函数timestampdiff()使用
  8. Carrot2 in action 初步印象
  9. 三菱plc pwm指令_学会了这27条基本逻辑指令,你离熟练编程三菱PLC又近了一步!...
  10. 3d数字孪生智慧城市大数据可视化建设方案
  11. Git从远程仓库取代码
  12. CentOS7防火墙关闭
  13. 174. 地下城游戏;剑指 Offer 40. 最小的k个数;378. 有序矩阵中第K小的元素;703. 数据流中的第K大元素
  14. 【阅读笔记】Gradient Harmonized Single-stage Detector
  15. 【评测】一种组织蛋白快速提取方法
  16. 【uni-app】uni-app实现聊天页面功能——功能篇(上)
  17. oracle 英文简写的日期转成数值型日期的字符串
  18. 论文写作-如何提高英语论文写作水平
  19. 迷你计算机工作站,这到底是什么 迄今最mini的工作站即将发售
  20. 一个蚂蚁前端曾经的辛酸面试历程 | 掘金技术征文

热门文章

  1. java本地储存set_没有数据库的情况下,JAVA如何在本地保存信息
  2. html语义化标签_9.28晨会分享 常见的HTML5语义化标签、实体字符
  3. python list拆分_python里如何把一个list分成两个
  4. div搜索框与按钮不在一行_这款漫画资源搜索软件,堪称二次元迷的必备神器!...
  5. ai智能和大数据测试_测试版可帮助您根据自己的条件创建数据和AI平台
  6. python如何获得列表中某个元素的index
  7. mysql上线脚本规范_MySQL 的 21 个规范、优化最佳实践!
  8. MFC CListCtrl 将一个列表的选中项添加到另一个列表
  9. 程序员又双叒叕开始装逼了,这次用代码写合租广告,网友神评亮了
  10. 大型网站架构系列:负载均衡详解