【自学笔记】之LINUX入门的那些破事儿——awk入门

入门第一讲:awk调用方法

awk语句都是由模式(pattern)和动作(action)组成

1.awk三种调用方式整理

①命令行调用

1.新建一个文件input

2.输入2个回车,保存

3.做正则匹配打入如下命令awk '/^$/{print "this is a blank line."}' input

[zhangyongqiao.pt@v128217:~$] cat input

[zhangyongqiao.pt@v128217:~$] awk '/^$/{print "this is a blank line."}' input

this is a blank line.

this is a blank line.

注:模式:/^$/ 的正则表达式匹配的是空白行

动作:print "this is a blank line."

②脚本间接调用

1.新建文件src.awk 输入如下cat到的内容

2.使用awk -f 调用src.awk文件

[zhangyongqiao.pt@v128217:~$] cat src.awk

/^$/{print "this is a blank line."}

[zhangyongqiao.pt@v128217:~$] awk -f src.awk  input

this is a blank line.

this is a blank line.

注:这里的awk -f src.awk  命令段相当于awk '/^$/{print "this is a blank line."}' 

③脚本直接调用

1.修改src.awk文件,修改内容参照cat到的部分

2.直接运行./src.awk + 待读入文件名

[zhangyongqiao.pt@v128217:~$] cat src.awk

#!/bin/awk -f #用了那么久,今天终于知道“#!”叫“sha-bang符号”

/^$/{print "this is a blank line."}

[zhangyongqiao.pt@v128217:~$] ./src.awk input

this is a blank line.

this is a blank line.

注:这里的 ./src.awk  命令段相当于awk '/^$/{print "this is a blank line."}' 

入门第二讲:记录和域

文件的一行称为一条记录,一条记录的每一个字符串称为一个域,域以空格。TAB及其他符号(, . 、等)分割。

例2:记录和域的一些常用方式

首先编辑input文件如下:#小空格为空格键,大空格为TAB

对第一条记录做解释:zhang yi 001 1989 分别为第一条记录对应的4个域

=======================================================

[zhangyongqiao.pt@v128217:~$] cat input

zhang yi        001     1989

zhang er        002     1990

zhang san       003     1991

========================================================

①利用域操作符$对文件做简单的处理

[zhangyongqiao.pt@v128217:~$] awk '{print $1,$2,$3}' input

zhang yi 001

zhang er 002

zhang san 003

②配合变量运算表达式对文件处理

[zhangyongqiao.pt@v128217:~$] awk 'BEGIN {A=1} {print $(1+A)}' input

yi

er

San

################################################################

这里引入一个关于BEGIN的解释

用法:BEGIN后面跟着的一个表达式在文件读入之前执行一次

[zhangyongqiao.pt@v128217:~$] awk 'BEGIN {A=0}{A++} {print $(1+A)}' input

yi                                 #A=1                         

002 #A=2

1991 #A=3

[zhangyongqiao.pt@v128217:~$] awk 'BEGIN {A=0;A++} {print $(1+A)}' input

yi #A=1

er #A=1

san #A=1

第一条命令{A=0}在读入文件之前执行了一次,后面的命令在每行循环时重复执行

第二条命令{A=0;A++}在读入文件之前执行了一次,后面的命令在每行循环时重复执行

注:awk循环原理与sed一样,可以参见上一篇sed入门的最后一部分

################################################################

③使用FS变量改变分隔符

首先对文本进行一点小改动,将所有的空格和TAB换成逗号

[zhangyongqiao.pt@v128217:~$] cat input

zhang,yi,001,1989

zhang,er,002,1990

zhang,an,003,1991

[zhangyongqiao.pt@v128217:~$] awk 'BEGIN {FS=","} {print $2}' input

yi

er

An

****************************************************************

这里大家都知道了$1,$2...的意义了,那么$0又是什么呢?演示一下:

[zhangyongqiao.pt@v128217:~$] awk 'BEGIN {FS=","} {print $0}' input

zhang,yi,001,1989

zhang,er,002,1990

zhang,an,003,1991

这下不用解释也知道了吧。$0表示的就是一行记录里面所有的域

****************************************************************

入门第三讲:关系和布尔运算符

讲在前面:

这里就不列举常用布尔运算符了(< > = !=....

2个比较特色的运算符:

1.~ 匹配正则表达式

2.!~不匹配正则表达式

3.正则表达式与运算符的使用举例

首先看一个系统配置文件~~~~~~~嘿嘿。存密码的哦~

################################################################

[zhangyongqiao.pt@v128217:~$] cat /etc/passwd

root:x:0:0:root:/root:/bin/bash

bin:x:1:1:bin:/bin:/sbin/nologin

……

……

……

################################################################

①使用正则表达式~

#第一个域匹配root

[zhangyongqiao.pt@v128217:~$] awk 'BEGIN {FS=":"} $1~/root/' /etc/passwd

root:x:0:0:root:/root:/bin/bash

#所有域匹配root

[zhangyongqiao.pt@v128217:~$] awk 'BEGIN {FS=":"} $0~/root/' /etc/passwd

root:x:0:0:root:/root:/bin/bash

operator:x:11:0:operator:/root:/sbin/nologin

#所有域不匹配nologin

[zhangyongqiao.pt@v128217:~$] awk 'BEGIN {FS=":"} $0~/nologin/' /etc/passwd

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

②使用if语句等

观察文件第三个域与第四个域 做如下尝试

[zhangyongqiao.pt@v128217:~$] awk 'BEGIN {FS=":"} {if($3==$4) 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

nobody:x:99:99:Nobody:/:/sbin/nologin

nscd:x:28:28:NSCD Daemon:/:/sbin/nologin #省略后面的部分

当然,if也可以如其他编程语言规则一样进行多条件匹配

[zhangyongqiao.pt@v128217:~$] awk 'BEGIN {FS=":"} {if ($3==$4&&$4==0) print $0}' /etc/passwd

root:x:0:0:root:/root:/bin/bash

[zhangyongqiao.pt@v128217:~$]#

注:运算符基本操作就是如此了,其他的就不再特意举例说明

入门第四讲:表达式

~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

表达式区别于布尔运算符

所谓表达式最典型的就是(inta+intb=intc的操作

而布尔运算指的是a<b之类的操作,返回值为0或者1

~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

4.表达式1

①简单的除法运算

[zhangyongqiao.pt@v128217:~$] cat input

zhang,yi,001,1989

zhang,er,002,1990

zhang,an,003,1991

[zhangyongqiao.pt@v128217:~$] awk 'BEGIN {FS=","} {a=$4; b=a/2; print b}' input

994.5

995

995.5

入门第五讲:系统变量

关于系统变量,这里举出几个例子,详细的表格可以参看一些专门的文档

……………………………………………………………………………………

变量名 意义

$0 记录的所有域

$n 当前记录的第n个域

FILENAME 当前使用的文件名

NF 当前记录中域的数量

NR 当前记录数

……………………………………………………………………………………

5.对如上提到的一些系统变量做实践

[zhangyongqiao.pt@v128217:~$] cat input

zhang,yi,001,1989

zhang,er,002,1990

zhang,an,003,1991

[zhangyongqiao.pt@v128217:~$] awk 'BEGIN {FS=","} {print NF,NR,$0} END{print FILENAME}' input

4 1 zhang,yi,001,1989

4 2 zhang,er,002,1990

4 3 zhang,an,003,1991

入门第六讲:格式化输出

语法规则基本上等同于c语言的printf使用

基本语法如下:

Printf(格式控制符,参数)

###############################################################

所谓的格式控制符也就是(举例说明,不全)

格式符 意义

%c 字符

%s 字符串

%d 整型

%e 浮点数(科学记数)

%f 浮点数

%s 字符串

################################################################

6.基本用法举例

对同一种输出,给出三种不同的命令

[zhangyongqiao.pt@v128217:~$] awk 'BEGIN {FS=","} {printf("%s%d",$1,$4)}' input

zhang1989zhang1990zhang1991[zhawk 'BEGIN {FS=","} {printf("%s%d\n",$1,$4)}' input

zhang1989

zhang1990

zhang1991

[zhangyongqiao.pt@v128217:~$] awk 'BEGIN {FS=","} {printf("%s\t%d\n",$1,$4)}' input

zhang   1989

zhang   1990

zhang   1991

注:第一条命令在行尾缺少\n,不进行换行,导致第二条命令直接接在第一条命令的输出之后。

那么printfprint的区别何在呢?我们来看下面2行命令的输出

[zhangyongqiao.pt@v128217:~$] awk 'BEGIN {FS=","} {printf("%s\t%d\n",$1,$4)}' input

zhang   1989

zhang   1990

zhang   1991

[zhangyongqiao.pt@v128217:~$] awk 'BEGIN {FS=","} {print("%s\t%d\n",$1,$4)}' input

%s      %d

 zhang 1989

%s      %d

 zhang 1990

%s      %d

 zhang 1991

通过输出对比,很容易看出,对于制表符(\t)的处理2者是一样的,但是对于格式符,是printf特有的,在print的基本语法中是不包含这些格式符的。因此他们不能被识别,只能原样输出。

————————————————————————————————

注意:对于第2条命令的246行,

这三行前面都有空格符,这个是怎么回事呢?

看命令行对比:【注意,这里是print,而非printf

[zhangyongqiao.pt@v128217:~$] awk 'BEGIN {FS=","} {print("",$1,$4)}' input

 zhang 1989

 zhang 1990

 zhang 1991

[zhangyongqiao.pt@v128217:~$] awk 'BEGIN {FS=","} {print("" $1,$4)}' input

zhang 1989

zhang 1990

zhang 1991

So,在print中,双引号直接被识别成一个字段,这个空格是因为逗号引起的

————————————————————————————————

入门第七讲:内置字符串函数

按照惯例,先列举一些常用的函数

****************************************************************

函数名 意义

gsub(r,s) 在输入文件中s替换r

gsub(r,s,t)                t字符串中用s替换r

index(s,t) 取出t字符串中s所在的位置

length(s) s字符串的长度

match(s,t)                t字符串中是否有s

split(r,s,t)                t上将r分成序列s      

sub(r,s,t)                 t中第一次出现的r替换成s

substr(r,s,t)               返回r中从s开始的后缀部分

sbustr(r,s,t) 返回字符串r中从s开始长度为t的后缀部分

***************************************************************

7.关于内置字符串函数的使用

[zhangyongqiao.pt@v128217:~$] awk 'BEGIN {print index("abcdef","a")}'

1

简单的,在abcdef字符串中找到a字符的位置,也就是第一位

注意:这里的indexJAVA中的indexof使用有区别,java中数组下标为0的位为第一位,而这里第一位就是字符串的第一个字符所在的位置。

========================================================

BEGIN的一些强化

[zhangyongqiao.pt@v128217:~$] awk 'BEGIN {print index("abcdef","a")}'

1

[zhangyongqiao.pt@v128217:~$] awk '{print index("abcdef","a")}'

1

1

从上面2段命令对比可以很显然看到区别,对于BEGIN的定义是在文档读入前进行一次操作。因此不给出文档名,整段print语句也能执行

那么,对于第二条命令,awk命令一直在等待输入一个文档,然后对文档的每一行进行print语句操作。

========================================================

入门第八讲:向awk脚本传递参数

脚本内的变量可以在命令行中进行赋值,实现向awk脚本传递参数

8.在脚本中使用命令行的参数

[zhangyongqiao.pt@v128217:~$] cat output.awk

#!/bin/awk -f

{print ("The line number is "NR" ,Define is "Define"" )}

[zhangyongqiao.pt@v128217:~$] ./output.awk Define=3 FS="," input

The line number is 1 ,Define is 3

The line number is 2 ,Define is 3

The line number is 3 ,Define is 3

这一段没有特别需要注意的,将脚本语句转到命令行中就很简单了。

以上的操作在命令行中也就是:

[zhangyongqiao.pt@v128217:~$] awk  'FS=",",Define=3 {print ("The line number is "NR" ,Define is "Define"" )} ' input

The line number is 1 ,Define is 3

The line number is 2 ,Define is 3

The line number is 3 ,Define is 3

一个小问题:希望得到解决

————————————————————————————————

[zhangyongqiao.pt@v128217:~$] awk  'Define=3 {print ("The line number is "NR" ,Define is "Define"" )} ' input

The line number is 1 ,Define is 3

The line number is 2 ,Define is 3

The line number is 3 ,Define is 3

[zhangyongqiao.pt@v128217:~$] awk  'Define=3 {print ("The line number is "NR" ,Define is "Define"" )} FS=","' input

The line number is 1 ,Define is 3

zhang,yi,001,1989

The line number is 2 ,Define is 3

zhang,er,002,1990

The line number is 3 ,Define is 3

zhang,an,003,1991

————————————————————————————————

为什么上面3条类似的命令打印出来的结果却不一样呢?

入门第九讲:简单的条件语句与循环语句

循环和条件语句与一般语言类似,这里就不展开讨论了。给出例9

9.简单的条件判断语句

[zhangyongqiao.pt@v128217:~$] awk 'BEGIN{i=1} {if(i==NR){print"The line number is "NR""} i++}' input

The line number is 1

The line number is 2

The line number is 3

入门第十讲:数组

数组的基本格式:array[index]=value

区别:在awk中,无需定义数组的大小,不像c语言那样,以连续的地址存储。Awk的数组称之为关联数组,类似于key-value的形式,也就是说index的位置可以是小数或者是字符串

9.简单的数组应用

①基本命令

[zhangyongqiao.pt@v128217:~$] awk 'BEGIN{data[10.1]="120";;printf("%s\n",data[10.1])}'

120

[zhangyongqiao.pt@v128217:~$] awk 'BEGIN{data[10]="120";;printf("%s\n",data[10])}'

120

[zhangyongqiao.pt@v128217:~$] awk 'BEGIN{data['a']="120";;printf("%s\n",data['a'])}'

120

上述三个命令很好的解释了awk的数组与一般编程语言中数组的区别。

②判断一个数组元素是否存在的方式

[zhangyongqiao.pt@v128217:~$] awk 'BEGIN{data['a']="120"; if('a' in data) print"ok"}'

ok

split函数应用

Splitr,s.t)将r字符串以t字符串划分,结果存入s数组中

[zhangyongqiao.pt@v128217:~$] cat input

zhang,yi,001,1989

zhang,er,002,1990

zhang,an,003,1991

[zhangyongqiao.pt@v128217:~$] awk 'BEGIN {FS=","} {split($1,name,"n"); for (i in name) print name[i]}' input

zha

g

zha

g

zha

g

对于$1也就是字符串“zhang”的操作,以“n”为分隔符,对这个字符串划分,然后打印,分隔符不打印

④数组形式的系统变量

ARGV储存命令行参数,ARGCARGV中参数的个数,下面的命令直观的体现了他们的用法。

[zhangyongqiao.pt@v128217:~$] awk 'BEGIN{for(x=0;x<ARGC;x++)print ARGV[x];print ARGC}' xyz n=99 "hello"

awk

xyz

n=99

hello

4

到这里,sedawk编程的入门就结束了,sed用于刘编辑,将一系列的编辑命令作用于缓冲区中的输入文件的副本,从而实现了对输入文件的各种编辑操作。而awk的一大显著特点是处理结构化文件,所谓的结构化文件,是指划分为记录和与的文件,并且awk提供printf语句能生成格式化报表。

这里分享一本经典的sedawk深入书籍:

O'reilly&Associcates2000年出版的由Arnold Robbin 编著的sed&awk Pocket Peference

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值