您当前的位置: 首页 > 技术文章 > 前端开发

文本三剑客awk:命令讲解

作者: 时间:2023-06-08阅读数:人阅读

awk-命令讲解:

一、awk:

1.定义:

(1)在 Linux/UNIX 系统中,awk 是一个功能强大的编辑工具,逐行读取输入文本,默认以空格或tab键作为分隔符作为分隔。并按模式或者条件执行编辑命令。AMK信息的读入也是逐行指定的匹配模式进行查找,对符合条件的内容进行格式化输出或者过滤处理。

(2)可以在无交互的情况下实现相当复杂的文本操作,被广泛应用于 Shell脚本,完成各种自动化配置任务。

(3)总结:按命令找到指定行然后打印,awk默认操作是打印。

2.格式:

awk ‘(操作符) (怎么做)’ (处理对象)

3.工作过程:

(1)执行BEGIN{action;…}语句块中的语句。

(2)从文件或标准输入(stdin)中读取一行,然后执行{action;…}语句块,逐行扫描文件,从第一行到最后一行重复执行,直到文件全部读取完成。

(3)当读至输入流末尾时,执行END{action;…}语句块,BEGIN语句块在awk开始从输入流中读取行之前被执行,这是一个可选的语句块,比如变量初始化、打印输出表格的表头等语句通常可以写在BEGIN语句块中。END语句块在awk从输入流中读取完所有的行之后即被执行,比如打印所有行的分析结果这类信息汇总都是在END语句块中完成,它也是一个可选语句块。pattern语句块中的通用命令是最重要的部分,也是可选的。如果没有提供pattern语句块,则默认执行{ print },即打印每一个读取到的行,awk读取的每一行都会执行该语句块。

(4)总结:先看BEGIN{action},这个模块读取操作,读文件的所有行,所有读取完毕后,一次执行。END{action}打印输出结果,对前面的结果作条件判断,还可用代码操作。

4.工作原理:

sed命令常用于一整行的处理,而awk比较倾向于将一行分成多个“字段”然后再进行处理,且默认情况下字段的分隔符为空格或 tab 键。awk 执行结果可以通过 print 的功能将字段数据打印显示。

5.常用选项:

(1)常用:

选项 作用
-F “分隔符” 指明输入时用到的字段分隔符,默认是若干个连续的空白符
-v 变量赋值

(2)常用符号:

选项 作用
‘’ ‘模式或条件{操作}’,{}外指定条件,{}内指定条件
, 指定连续的行
|| 指定不连续的行
&& 表示且

(3)内置变量(不能用双引号,否则会被系统识别成字符串):

选项 作用
$0 打印当前处理行的所有内容
$n 对当前处理行的第n个字段(第n列)
NR 当前处理行的行号(序数)
NF 当前处理行的n个字段
FS 列分隔符,指定每行文本的字段分隔符,输入内容的分隔符,默认为空格或制表位。与"-F"作用相同 用-F可以不加单引号 -F:,用FS必须用=“”
OFS 输出内容的列分隔符
RS 行分隔符。awk从文件中读取资料时,将根据RS的定义把资料切割成许多条记录,而awk一次仅读入一条记录进行处理。预设值是"\n"
Fillname 被处理的文件名

(4)基本打印用法:

1.[root@test1 opt]# awk '0{print}' test.txt  # 0和1放置{ }前,能够起到限制打印内容的作用(默认为"1"),如果为0,就不打印内容
[root@test1 opt]# awk '1{print}' test.txt 
bk
pp
chanyeol
baekhyun
2. [root@test1 opt]# awk '{print $0}' test.txt #$0,代表整行内容;awk是逐行读取处理,配合$0,就是打印所有内容
$1只取第一列,可以对行切片,输出列
bk
pp
chanyeol
baekhyun
[root@test1 opt]# awk '{print NR}' test.txt #打印行号
1
2
3
4
[root@test1 opt]# awk '{print NR,$0}' test.txt #打印行号和内容
1 bk
2 pp
3 chanyeol
4 baekhyun
3. [root@test1 opt]# awk 'NR==3{print}' test.txt #指定打印第三行
chanyeol
[root@test1 opt]# awk 'NR==2,NR==4{print}' test.txt #指定打印2-4行
pp
chanyeol
baekhyun
[root@test1 opt]# awk 'NR==2;NR==4{print}' test.txt #指定打印第二行,第四行
pp
baekhyun
[root@test1 opt]# awk '(NR>=2)&&(NR<=4){print}' test.txt #用正则表达式打印2-4行
pp
chanyeol
baekhyun

(2)奇偶行打印:

[root@test1 opt]# awk 'NR%2==0{print}' test.txt #偶数行打印
pp
baekhyun
[root@test1 opt]# awk 'NR%2==1{print}' test.txt #奇数行打印
bk
chanyeol

(3)运算:

[root@test1 ~]# awk 'BEGIN{print 100+200}'
300
[root@test1 ~]# awk 'BEGIN{print 10.2*5.5}'
56.1
[root@test1 ~]# awk 'BEGIN{print 10.2/5.5}'
1.85455
[root@test1 ~]# awk 'BEGIN{print 2^5}'
32

二、内置函数:

1.getline的工作过程:

(1)当getline左右无重定向符号(“<”,“>”)或者管道符号(“|”)时,awk首先读取的是第一行,而getline获取的是光标跳转至下一行的内容(也就是第二行)。

(2)当getline左右有管道符号或重定向符时,getline则作用定向输入文件,由于文件是刚打开,并没有被awk读入一行,而只是getline读入,所以getline返回的是文件的第一行,而不是跳转至一行输入。

2.打印:

(1)基本运用:

[root@test1 opt]# awk '{print $0;getline}' test.txt #打印奇数行
bk
chanyeol
[root@test1 opt]# awk '{getline;print $0}' test.txt #打印偶数行
pp
baekhyun

(2)总结:

  • getline是awk的内置函数。
  • 没有重定向,管道符,就打印奇偶行。
  • 重定向从指定文件获取内容,管道符相当于赋值变量。

3.文件内容匹配过滤打印:

(1)基础打印:

1.[root@test1 opt]# awk '/^root/{print}' /etc/passwd #只匹配以root开头的行
root:x:0:0:root:/root:/bin/bash
2.[root@test1 opt]# awk '/root/{print}' /etc/passwd #只匹配包含root的行
root:x:0:0:root:/root:/bin/bash
operator:x:11:0:operator:/root:/sbin/nologin
3.[root@test1 opt]# awk '/bash$/{print}' /etc/passwd #只匹配以bash结尾的行
root:x:0:0:root:/root:/bin/bash
wang:x:1000:1000:wang:/home/wang:/bin/bash
billkin:x:1001:1001::/home/billkin:/bin/bash
pp:x:1002:1002::/home/pp:/bin/bash
chanyeol:x:1003:1003::/home/chanyeol:/bin/bash
baekhyun:x:1004:1004::/home/baekhyun:/bin/bash
chanbaek:x:1005:1005::/home/chanbaek:/bin/bash
suho:x:1006:1006::/home/suho:/bin/bash

4.BEGIN,END模式:

(1)BEGIN打印模式:

  • 格式:awk ‘BEGIN{…};{…};END{…}’ 文件
  • 处理过程:在awk处理指定的文本之前,需要先执行BEGIN{…}模式里的命令操作。中间的{…} 是真正用于处理文件的命令操作,在awk处理完文件后才会执行END{…}模式里的命令操作。END{ }语句块中,往往会放入打印结果等语句。
  • 固定格式:awk ‘BEGIN{X=1}(初始条件);{x++}(命令操作);END{print x}(打印结果)’ 文件名

(2)运用:

1. [root@test1 opt]# awk 'BEGIN{x=1};{x++};END{print x}' test1.txt
5
2.[root@test1 opt]# head -n5 /etc/passwd |awk  -F: '{print $1}' #以冒号为分割,打印第一列
root
root
bin
daemon
adm
lp

(3)-v 变量赋值:

1. [root@test1 opt]# fs=":";awk -v FS=$fs -v OFS="+" '{print $1,$3}' /etc/passwd 
root+0 # fs的列分隔符是:,然后使用-v给FS赋值=:,输入的时候FS是:,-v给OFS赋值输出的时候变量为+,然后打印第一列和第三列
bin+1
daemon+2
adm+3
lp+4
sync+5
shutdown+6
2. [root@test1 opt]# echo $PATH | awk -v RS=':' '{print $1}' #换行输出
/usr/local/sbin
/usr/local/bin
/usr/sbin
/usr/bin
/root/bin

5.条件判断打印:

(1)指定区间打印:

[root@test1 opt]# awk -F : '$3>500{print $0}' /etc/passwd #uid大于500的
polkitd:x:999:998:User for polkitd:/:/sbin/nologin
libstoragemgmt:x:998:996:daemon account for libstoragemgmt:/var/run/lsm:/sbin/nologin
colord:x:997:995:User for colord:/var/lib/colord:/sbin/nologin

(2)取反打印:

[root@test1 opt]# awk -F : '!$3<=10{print $0}' /etc/passwd
root:x:0:0:root:/root:/bin/bash
bin:x:1:1:bin:/bin:/sbin/nologin

(3)用if做条件判断来打印:

[root@test1 opt]# awk -F : '{if($3>10){print $0}}' /etc/passwd
operator:x:11:0:operator:/root:/sbin/nologin
games:x:12:100:games:/usr/games:/sbin/nologin #使用了if语句,内部条件(),外部条件{},整个加{}作为一条语句执行,相当于嵌套语法

三、awk的三元表达式:

1.格式:

(1)awk ‘(条件表达式)?(A表达式或者值):(B表达式或者值)’

(2)运用:

[root@test1 opt]# awk -F: '{max=($3>=$4)?$3:$4;{print max,$0}}' /etc/passwd|sed -n '1,6p'

在这里插入图片描述

2.awk的精确筛选:

(1)常用选项:

选项 作用
$n(> < ==) 用于对比数值
$n~“字符串” 代表第n个字段包含某个字符串
$n!~“字符串” 代表第n个字段不包含某个字符串
$n==“字符串” 代表第n个字段为某个字符串
$n!=“字符串” 代表第n个字段不为某个字符串
$NF 代表最后一个字段

(2)基础运用:

1. [root@test1 opt]# awk -F: '$7~"bash" {print $1,$NF}' /etc/passwd 
root /bin/bash # 输出第七个字段包含“bash”所在行的第一个字段和最后一个字段
wang /bin/bash
billkin /bin/bash
pp /bin/bash
chanyeol /bin/bash
baekhyun /bin/bash
chanbaek /bin/bash
suho /bin/bash
2.[root@test1 opt]# awk -F: '$7!~"nologin" {print $1,$NF}' /etc/passwd
root /bin/bash # 输出第七个字段不包含“nologin”所在行的第一个字段和最后一个字段
sync /bin/sync
shutdown /sbin/shutdown
halt /sbin/halt
wang /bin/bash
billkin /bin/bash
pp /bin/bash
chanyeol /bin/bash
baekhyun /bin/bash
chanbaek /bin/bash
suho /bin/bash
3.[root@test1 opt]# awk -F: '($6=="/home/wang")&&($7=="/bin/bash"){print $1,$NF}' /etc/passwd
wang /bin/bash指定第六个字段为/home/wang,第七个字段为/bin/bash,输出满足这些条件所在行的第一个和最后一个字段

3.数组:

(1)基础运用:

1.[root@test1 opt]# awk 'BEGIN{a[0]=1;a[1]=2;a[2]=3;print a[1]}' 
2
2.[root@test1 opt]# awk 'BEGIN{a[0]=10 ; a[1]=20 ; a[2]=30;for(i in a)print i,a[i]}' #数组遍历
0 10
1 20
2 30

(2)去重:

[root@test1 opt]# awk '{a[$1]++};END{for(i in a){print i,a[i]}}' test1.txt  
baekhyun 1
chanyeol 1
pp 3
bk 3

本站所有文章、数据、图片均来自互联网,一切版权均归源网站或源作者所有。

如果侵犯了你的权益请来信告知我们删除。邮箱:licqi@yunshuaiweb.com

加载中~
如果您对我们的成果表示认同并且觉得对你有所帮助可以给我们捐赠。您的帮助是对我们最大的支持和动力!
捐赠我们
扫码支持 扫码支持
扫码捐赠,你说多少就多少
2
5
10
20
50
自定义
您当前余额:元
支付宝
微信
余额

打开支付宝扫一扫,即可进行扫码捐赠哦

打开微信扫一扫,即可进行扫码捐赠哦

打开QQ钱包扫一扫,即可进行扫码捐赠哦