awk

awk 独立的编程语言

Awk是一种处理结构数据并输出格式化结果的编程语言, Awk 是其作者 "Aho,Weinberger,Kernighan" 的简称。
Awk通常被用来进行格式扫描和处理。通过扫描一个或多个文件中的行,查看是否匹配指定的正则表达式,并执行相关的操作。
Awk的主要特性包含:

  1. Awk以记录和字段的方式来查看文本文件
  2. 和其他编程语言一样,Awk 包含变量、条件和循环
  3. Awk能够进行运算和字符串操作
  4. Awk能够生成格式化的报表数据

Awk从一个文件或者标准输入中读取数据,并输出结果到标准输出中。

1 awk功能2 awk的命令格式

格式一:
awk 选项 ‘处理动作’ 文件列表
格式二:
命令 | awk 选项 ‘处理动作’

3 awk对数据的处理方式

以行为单位对数据逐行处理,处理完当前行后自动处理下一行,直到处理完所有的行为止,默认把对数据处理的结果输出到屏幕。

4 选项

-F “分隔符” 指定分隔时使用的分隔符,默认列的分隔符为空格(至少一个)或tab,使用默认分隔符是可以省略

5 内置变量

5.1 12 3n

(使用字段分隔符后,对应列(域)的值)
打印某一列:
awk –F”:” ‘{print $1}’ /etc/passwd

打印某几列:
(若想打印多列时用,逗号分隔)
awk –F”:” ‘{print 1,3,$4}’ /etc/passwd

应用:IP地址的获取。
root@whatislinux:/home/whatispython/workspace/shell/sed# ifconfig | sed -n '/inet /p' | awk -F" " '{print 2}'  172.16.126.252  127.0.0.1  root@whatislinux:/home/whatispython/workspace/shell/sed# ifconfig | sed -n '/inet /p' | head -1 | awk -F" " '{print $2}'  172.16.126.252  5.20:保存当前处理行的内容

例子:
head –5 /etc/passwd | awk ‘{print “abcdef”}’
#由上知,每处理一行,打印一次字符串abcdef,若想打印当前处理的行呢?
使用0内置变量      head –5 /etc/passwd | awk ‘{print0}’
注意:在awk中调用自定义变量或内置变量是,不需要加双引号,如果加了,会被当成普通字符串输出。只有当要指定输出特定字符串时才需要加””双引号。

5.3 FILENAME:保存当前文件的文件名

awk ‘{print FILENAME}’ /etc/passwd

有多少行输出多少次

如果后面接多个文件呢
awk ‘{print FILENAME}’ a.txt b.txt
处理结果:
a.txt
a.txt
b.txt
b.txt
b.txt
b.txt
b.txt
具体执行过程:
先对第一个文件处理,有多少行输出多少个FILENAME,接下来再处理第2个文件,因有b.txt有5行,所以执行5次print动作,输出5次b.txt.

5.4 NF NR FNR

NF:使用字段分隔符后,每行包含列的个数

NR存储AWK当前处理行的行数
FNR: 存储AWK当前处理行对应文件中的行数
NR和FNR当处理文件是一个时,NF和FNR值相等

例子:
awk -F”:” ‘{print NR}’ /etc/passwd

awk –F”:” ‘{print $0,NR,FNR}’ /etc/passwd

如果后面接多个文件
awk –F”:” ‘{print 0,NR,$FNR}’ a.txt b.txt
会发现如果后面只有一个文件时NR和FNR的值是一样的,当后面接多个文件时NR>FNR,综上,NR>=FNR

6 awk处理数据的顺序(执行顺序)

BEGIN{} 行前处理
{} 行处理
END{} 行后处理

BEGIN{} 行前处理
awk在没有读入行前执行的动作,可以把初始化的操作都写在BEGIN{}容器中。

{} 行处理
awk对读入的每一行数据做处理的动作,把对数据处理的操作都写在{}容器中

END{} 行后处理
awk把所有行都读完之后,执行的处理动作,把处理结果的汇总输出都写在END{}容器中。

例子:
使用awk的输出对应列的数据时,给每一列加标题。(/etc/passwd)
如: username homedir shell
root /root /sbin/bash
bin /bin /sbin/nologin

注意:
在窗口中如果有多个处理动作时要使用;分号
awk ‘{print ENVIRON[“USER”]}’ a.txt
awk ‘{print ENVIRON[“USER”];print $0}’ a.txt

各个容器可以自由组合,也可以重复多次。如可以加多个行处理{}
awk ‘BEGIN{print “username\tuid\tgid”}{}’ a.txt

awk ‘BEGIN{print “username\tuid\tgid”}{print $1”\t”,$3”\t”,$4”\t”}END{print “FINISH”}’ a.txt

awk ‘{print $0}{print FILENAME}’ a.txt (等价于:awk ‘{print $0;print FILENAME}’ a.txt)
awk ‘BEGIN{}BEGIN{}’ a.txt
awk ‘END{}END{}’ a.txt

小结:
BEGIN{} 一般用于数据的初始化操作
{} 行要执行什么样的操作
END{} 所有行处理完成后

awk ‘BEGIN{print NR}{print NR}END{print NR}’ a.txt
0: BEGIN{print NR}的返回结果
1
2
3
4
5 :END{print NR}的返回结果

行前处理应用:初始化操作
默认分隔符为空格(至少一个)或tab,这个存放在FS这个内置变量中,可以用-F来指定(之前一直这么做),也可以用先前处理对其进行初始化。
如:
awk ‘BEGIN{FS=”:”}{print $1}’ a.txt
#在行处理前将默认分隔符改成:冒号。

注意区别:
awk ‘{print 1,2}’ a.txt
awk ‘{print 1;print2}’ a.txt
awk ‘{print 1}{print2}’ a.txt

#

7 条件的使用

默认文件有多少行,awk处理多少次,如果只想处理指定范围的行怎么办?
需求:用awk输出偶数行

在处理数据时,在前加上条件,让awk只处理符合条件的行
(不加条件时默认逐行处理,加了条件只有当前行或行里的数据符合条件时,才用处理动作处理。)

格式:
awk 选项 ‘条件{处理动作}’ 文件名

条件格式:(区别与sed)

1.1 数值比较

=
< <=
== !=
如:
awk -F ‘3<500{print1,$3}’ /etc/passwd
#统计当前系统有多少个内建用户、多少个外建用户(awk+wc –l,后面讲了awk的运算符后,可以使用另一种方法)

1.2 字符比较

!=

上面2个运算符后面接字符时要用双引号

1.3 逻辑比较:多个条件时使用
&& 逻辑与
|| 逻辑或
! 逻辑非

如:
awk -F “:” ‘1==root||1==”daemon”{print 1,3,$4}’ /etc/passwd

1.4 /正则表达式/
~ 与正则表达式匹配为真
!~ 与正则表达式不匹配为真

如:
值~/正则表达式/
值!~/正则表达式/

例子:
awk -F ‘1!~/[0-9]/{print1}’ /etc/passwd

8 awk运算符

+

*
/
%
+=
-=
*=
/=
%=


awk ‘{print i}’ a.txt
知:
awk中的变量不需要预先定义,可以直接调用。

例子:
[root@iLor awk]# cat a.txt
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
[root@iLor awk]# awd '{i=0;i++;print i}' a.txt
-bash: awd: command not found
[root@iLor awk]# awk '{i=0;i++;print i}' a.txt
1
1
1
1
1
[root@iLor awk]# awk '{i=0;i++;print i}' a.txt  #加后,i0也就是当前行的内容
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
[root@iLor awk]#
[root@iLor awk]#
[root@iLor awk]# awk 'BEGIN{i=0}{i++;print i}' a.txt
1
2
3
4
5
[root@iLor awk]# awk 'BEGIN{i=0}{i++}END{print i}' a.txt
5

awk ‘FNR%2==0{print FNR,$0}’ /etc/passwd


--------------------------
1-100含7或能被7整除的整数。
seq 100 | awk ‘NR~/7/||NR%7==0{print NR}’
seq 100 | awk ‘$0~/7/||$0%7==0{print $0;i++}END{print i}’

9 awk流程控制

9.1分支结构

9.1.1 单分支

格式1:if(条件判断){条件成立时执行的操作}
#条件用小括号括起来
#条件成立时执行后面的操作,不成立什么也不做
例子:
awk ‘{if(){}}’ /etc/passwd
#注意2个大括号意义区别

 具体执行过程:
   每行执行’’(单引号)中的动作,当if条件成立时才会执行第二个{}里面的操作。

awk ‘{if(NR==1||NR==10){print $0}}’ /etc/passwd
   #2个等号为比较判断,一个等号为赋值

条件成立时,才执行if中的操作,若不成立这一行就不处理了,再进行下一行处理(先判断条件)

格式2:if(条件判断)条件成立时执行的操作 #如果条件成立时,if(){}花括号中只有一个执行动作时,才可以将{}省略,否则,如果条件成立时,要执行多个动作,则{}花括号必须要有。
如:awk ‘{if(NR==1||NR==10)print NR,” ”0;print1 }’ /etc/passwd
#if(NR==1||NR==10)print NR,” ”0这是一个if整体             #print1 是一个整体
#表达的意思也发生了变化,当if条件成立时执行第一个print操作。
#即:每一行执行完if后,还要执行print $1的操作。

9.1.2 双分支

格式1:
   if(条件){指令1}else{指令2}
格式2:
   if()指令1;else指令2

9.1.3多分支

格式:
   if(条件){指令1}else if(条件){指令2}……else if(条件){指令3}else{指令}

10 awk脚本

补充sed中,如何调用shell变量

sed –n ‘namep’ /etc/passwd (x) #会报错,需要用单引号  sed –n ‘’name’p’ /etc/passwd (v) #注意单引号的配对(第一个和第4个,第二个和第三个)

awk中如何调用shell变量

注意:shell变量分为系统级的和用户自定义级别的。

如何调用系统级别的shell变量:

   格式:ENVIRON[“shell系统环境变量”]
   #这是一个数组类型的内置变量,用来在awk里面调用shell系统环境变量。
   #每个数组都是通过下标来引用,而这个内置变量数组是使用shell系统环境的变量名作为数组元素的下标来引用数据。

用户自定义变量如何调用:

   格式:-v选项的使用

来引出自定义的awk变量。

   例如:awk -v awk_name=$name ‘{print awk_name}’ a.txt
   #使用-v关键字来自己定义awk变量,一旦定义awk变量后,就可以在awk的动作处理中直接调用了。

小结:在执行awk时,想要调用shell里面的自定义变量,需要在执行过程中加上-v选项后接awk变量名,并将自定义shell变量的值赋值给awk变量,然后在处理动作中可以直接调用之前定义的awk变量(相当于间接调用shell中的自定义变量)。





posted @ 2019-01-30 17:29  whatislinux  阅读(215)  评论(0编辑  收藏  举报