awk命令的使用(初探)

2020-04-24  本文已影响0人  一只烟酒僧

参考文章:https://www.cnblogs.com/along21/p/10366886.html#重要!
参考文章:https://www.runoob.com/w3cnote/awk-work-principle.html#awk的工作原理
sed和awk的区别:https://www.zhihu.com/question/297858714
AWK简明教程:https://coolshell.cn/articles/9070.html
sed官方手册:http://www.gnu.org/software/sed/manual/sed.html
sed简明教程:https://coolshell.cn/articles/9104.html
sed命令简介1:http://linux.51yip.com/search/sed
sed命令简介2:https://man.linuxde.net/sed
sed命令简介3:https://www.runoob.com/linux/linux-comm-sed.html
awk内置函数使用说明:https://blog.csdn.net/w36680130/article/details/81029527

一、概述

awk是一个文本处理软件,更是一门语言,用于在linux下对文本进行处理。其输入可以是标准输入、文件(多个)或其它程序的输出,通过其高度灵活的文本处理方法,如正则表达式、自定义函数、内置变量、格式化输出等 对文本进行高效处理。本文仅对awk最最基础的原理及应用做总结。

二、awk的工作原理

与sed类似,awk本质上也采用了逐行处理的模式,首先awk会先运行一次标识为BEGIN{}的命令,一般是一些预设变量等,之后会将文本逐行读入变量中,通过模式匹配(正则)、函数等方法进行处理,将整个文件全部逐行处理完成之后,再通过表示END{}的命令完成后续操作,最终将结果输出为标准输出。


awk工作原理

与sed相比,awk在格式上更复杂,其语法也更规范化,包括了函数、自定义函数、循环、条件、变量等编程语言必备的要素,在学习过程中比sed更难,但功能更强大。

三、awk的命令模式

1、命令行的标准模式: awk [options] -v var=value 'BEGIN{action...}pattern{action...}END{action...}' file(s)
2、接受脚本文件的格式 :awk [options] -f programfile var=value file(s)
3、命令行的常用模式(简单模式):awk [options] -F 分隔符 ’command‘ file(s)

四、awk的参数、语法和应用实例

1、awk的参数

因为awk是门语言,所以很多功能都是通过语法实现的,参数比较少,常用的几个如下:
-F fs:fs指定输入分隔符,fs可以是字符串或正则表达式,如-F:
-v var=value:赋值一个用户定义变量,将外部变量传递给awk
-f scripfile:从脚本文件中读取awk命令
另注:基本上参数能实现的功能,语法都可以实现,只不过参数比较方便。

2、awk的语法

2.1 awk的变量

awk中可以更改内置变量的值或定义自己的变量,用两种方法,一种是通过-v 参数 如awk -v FS=\n '{}' file 另一种是直接在语句中定义,但要用引号,如 awk '{FS="\n";print FS} file

2.1.1 awk的内置变量

FS :输入字段分隔符,默认为空白字符,如FS=":",表示输入行的字段根据冒号分隔为不同列
OFS :输出字段分隔符,默认为空白字符,如OFS=“:”,表示输出行的字段中间插入冒号再合并分隔输出
RS :输入记录分隔符,指定输入时的换行符,原换行符仍有效,如 RS=":" ,意思是把输入行中的冒号替换成换行符
ORS :输出记录分隔符,输出时用指定符号代替换行符。如 ORS=":",意思是把输出的行中的换行符替换成冒号
NF :字段数量,即统计每行被分割成多少字段, NF可以表示最后一列,(NF-1)可以表示倒数第二列
NR :行号,后可跟多个文件,第二个文件行号继续从第一个文件最后行号开始
FNR :各文件分别计数, 行号,后跟一个文件和NR一样,跟多个文件,第二个文件行号从1开始
FILENAME :当前文件名
ARGC :命令行参数的个数 ,一般用在BEGIN里面
ARGV :数组,保存的是命令行所给定的各参数,查看参数 ,同上

2.1.1.1实例

实例文件一 :awkdemo

[root@along ~]# cat awkdemo
hello:world
linux:redhat:lalala:hahaha
along:love:youou
[root@along ~]# awk -v FS=':' '{print $1,$2}' awkdemo  #FS指定输入分隔符
hello world
linux redhat
along love
[root@along ~]# awk -v FS=':' -v OFS='---' '{print $1,$2}' awkdemo  #OFS指定输出分隔符
hello---world
linux---redhat
along---love
[root@along ~]# awk -v RS=':' '{print $1,$2}' awkdemo
hello
world linux
redhat
lalala
hahaha along
love
you
[root@along ~]# awk -v FS=':' -v ORS='---' '{print $1,$2}' awkdemo
hello world---linux redhat---along love---
[root@along ~]# awk -F: '{print NF}' awkdemo
2
4
3
[root@along ~]# awk -F: '{print $(NF-1)}' awkdemo  #显示倒数第2列
hello
lalala
love
[root@along ~]# awk '{print NR}' awkdemo awkdemo1
1
2
3
4
5
[root@along ~]# awk END'{print NR}' awkdemo awkdemo1
5
[root@along ~]# awk '{print FNR}' awkdemo awkdemo1
1
2
3
1
2
[root@along ~]# awk '{print FILENAME}' awkdemo
awkdemo
awkdemo
awkdemo
[root@along ~]# awk 'BEGIN {print ARGC}' awkdemo awkdemo1
3
[root@along ~]# awk 'BEGIN {print ARGV[0]}' awkdemo awkdemo1
awk
[root@along ~]# awk 'BEGIN {print ARGV[1]}' awkdemo awkdemo1
awkdemo
[root@along ~]# awk 'BEGIN {print ARGV[2]}' awkdemo awkdemo1
awkdemo1

2.1.2自定义变量

定义方法与上文一样,只不过变量名是用户自己起的。

2.2prinf 格式化输出

格式化输出:是指在输出处理结果的时候以用户自定义的某个样式进行输出。

2.2.1 语法

awk '{com;printf "FORMAT", item1,item2, ...}' file

FORMAT指用户想呈现的格式,item指在哪一个位置呈现,因此,format要与item在顺序上一一对应。
不会自动换行,需要显式给出换行控制符,\n
常用格式:awk '{prinf "%-10s %-10s %-10s %-10s\n",1,2,3,4}' file
常用格式说明:输出1-4行,格式为左对齐(-),至少显示10个字符,多于10个继续显示,不足十个空格补齐(%10s),列之间用空格分开,每行末尾加上换行符

格式符
%c: 显示字符的ASCII码
%d, %i: 显示十进制整数
%e, %E: 显示科学计数法数值
%f :显示为浮点数,小数 %5.1f,带整数、小数点、整数共5位,小数1位,不够用空格补上
%g, %G :以科学计数法或浮点形式显示数值
%s :显示字符串;例:%5s最少5个字符,不够用空格补上,超过5个还继续显示
%u :无符号整数
%%: 显示% 自身
修饰符
#[.#]:第一个数字控制显示的宽度;第二个# 表示小数点后精度,%5.1f
-:左对齐(默认右对齐) %-15s
+:显示数值的正负符号 %+d

2.2.2 实例

[root@along ~]# awk -F: '{print $1,$3}' /etc/passwd
root 0
bin 1
---第一列显示小于20的字符串;第2列显示整数并换行
[root@along ~]# awk -F: '{printf "%20s---%u\n",$1,$3}' /etc/passwd
                root---0
                 bin---1
---使用-进行左对齐;第2列显示浮点数
[root@along ~]# awk -F: '{printf "%-20s---%-10.3f\n",$1,$3}' /etc/passwd
root                ---0.000    
bin                 ---1.000
---使用printf做表格
[root@along ~]# awk -F: 'BEGIN{printf "username            userid\n-----------------------------\n"}{printf "%-20s|%-10.3f\n",$1,$3}' /etc/passwd
username            userid
-----------------------------
root                |0.000    
bin                 |1.000

2.3 操作符

2.3.1 类型

写在前面:比较重要的操作符为 模式匹配符 ~ 逻辑操作符 函数调用符和条件表达式(类似于R中的ifelse函数)
算术操作符:
x+y, x-y, x*y, x/y, x^y, x%y
-x: 转换为负数
+x: 转换为数值
字符串操作符:没有符号的操作符,字符串连接
赋值操作符:
=, +=, -=, *=, /=, %=, ^=
++, --
比较操作符:
==, !=, >, >=, <, <=
模式匹配符:~ :左边是否和右边匹配包含 !~ :是否不匹配
逻辑操作符:与&& ,或|| ,非!
函数调用: function_name(argu1, argu2, ...)
条件表达式(三目表达式):selector?if-true-expression:if-false-expression
注释:先判断selector,如果符合执行 ? 后的操作;否则执行 : 后的操作

2.3.2 实例

1、模式匹配符

---查询以/dev开头的磁盘信息
[root@along ~]# df -h |awk -F: '$0 ~ /^\/dev/'
/dev/mapper/cl-root   17G  7.3G  9.7G  43% /
/dev/sda1           1014M  121M  894M  12% /boot
---只显示磁盘使用状况和磁盘名
[root@along ~]# df -h |awk '$0 ~ /^\/dev/{print $(NF-1)"---"$1}'
43%---/dev/mapper/cl-root
12%---/dev/sda1
---查找磁盘大于40%的
[root@along ~]# df -h |awk '$0 ~ /^\/dev/{print $(NF-1)"---"$1}' |awk -F% '$1 > 40'
43%---/dev/mapper/cl-root

2、逻辑操作符

[root@along ~]# awk -F: '$3>=0 && $3<=1000 {print $1,$3}' /etc/passwd
root 0
bin 1
[root@along ~]# awk -F: '$3==0 || $3>=1000 {print $1}' /etc/passwd
root
[root@along ~]# awk -F: '!($3==0) {print $1}' /etc/passwd
bin
[root@along ~]# awk -F: '!($0 ~ /bash$/) {print $1,$3}' /etc/passwd
bin 1
daemon 2

3、条件表达式

[root@along ~]# awk -F: '{$3 >= 1000?usertype="common user":usertype="sysadmin user";print usertype,$1,$3}' /etc/passwd
sysadmin user root 0
common user along 1000

2.4 模式匹配操作(重点!!)

重点:awk的模式匹配操作与sed类似,基本代码逻辑都是 address{comd} 格式
(1)如果未指定:空模式,匹配每一行
(2)/regular expression/ :仅处理能够模式匹配到的行,正则,需要用/ / 括起来
(3)relational expression:关系表达式,结果为“真”才会被处理
真:结果为非0值,非空字符串
假:结果为空字符串或0值
(4)line ranges:行范围
startline(起始行),endline(结束行):/pat1/,/pat2/ 不支持直接给出数字,可以有多段,中间可以有间隔
(5)BEGIN/END 模式
BEGIN{}: 仅在开始处理文件中的文本之前执行一次
  END{} :仅在文本处理完成之后执行
实例如下

[root@along ~]# awk -F: '{print $1}' awkdemo
hello
linux
along
[root@along ~]# awk -F: '/along/{print $1}' awkdemo
along
[root@along ~]# awk -F: '1{print $1}' awkdemo
hello
linux
along
[root@along ~]# awk -F: '0{print $1}' awkdemo
[root@along ~]# awk -F: '/^h/,/^a/{print $1}' awkdemo
hello
linux
along
[root@along ~]# awk -F: 'BEGIN{print "第一列"}{print $1} END{print "结束"}' awkdemo
第一列
hello
linux
along
结束

2.5 awk的高阶使用

2.5.1 条件语句

if(condition){statement;…}[else statement] 双分支
if(condition1){statement1}else if(condition2){statement2}else{statement3} 多分支

2.5.2 for循环

for(expr1;expr2;expr3) {statement;…}
for(var in array) {for-body}

2.5.3 字符串处理(重点!!语法上与R中对应的函数一样)

length([s]) :返回指定字符串的长度
sub(r,s,[t]) :对t 字符串进行搜索r 表示的模式匹配的内容,并将第一个匹配的内容替换为s
gsub(r,s,[t]) :对t 字符串进行搜索r 表示的模式匹配的内容,并全部替换为s 所表示的内容
plit(s,array,[r]) :以r 为分隔符,切割字符串s ,并将切割后的结果保存至array 所表示的数组中,第一个索引值为1, 第二个索引值为2,…

2.5.4 其它高阶(以后填坑)

awk其它循环模式
awk自定义函数
awk数组
awk中调用shell 命令

上一篇下一篇

猜你喜欢

热点阅读