`
su1216
  • 浏览: 671891 次
  • 性别: Icon_minigender_1
  • 来自: 北京
博客专栏
Group-logo
深入入门正则表达式(jav...
浏览量:71996
E60283d7-4822-3dfb-9de4-f2377e30189c
android手机的安全问...
浏览量:128905
社区版块
存档分类
最新评论

《Linux命令行与shell脚本编程大全》 第二十一章 学习笔记

阅读更多

 

第一部分:Linux命令行
《Linux命令行与shell脚本编程大全》 第一章:初识Linux shell
《Linux命令行与shell脚本编程大全》 第二章:走进shell
《Linux命令行与shell脚本编程大全》 第三章:基本的bash shell命令
《Linux命令行与shell脚本编程大全》 第四章:更多的bash shell命令
《Linux命令行与shell脚本编程大全》 第五章:使用Linux环境变量
《Linux命令行与shell脚本编程大全》 第六章:理解Linux文件权限
《Linux命令行与shell脚本编程大全》 第七章:管理文件系统
《Linux命令行与shell脚本编程大全》 第八章:安装软件程序
《Linux命令行与shell脚本编程大全》 第九章:使用编辑器

第二部分:shell脚本编程基础
《Linux命令行与shell脚本编程大全》 第十章:构建基本脚本
《Linux命令行与shell脚本编程大全》 第十一章:使用结构化命令
《Linux命令行与shell脚本编程大全》 第十二章:更多的结构化命令
《Linux命令行与shell脚本编程大全》 第十三章:处理用户输入
《Linux命令行与shell脚本编程大全》 第十四章:呈现数据
《Linux命令行与shell脚本编程大全》 第十五章:控制脚本

第三部分:高级shell编程
《Linux命令行与shell脚本编程大全》 第十六章:创建函数
《Linux命令行与shell脚本编程大全》 第十七章:图形化桌面上的脚本编程
《Linux命令行与shell脚本编程大全》 第十八章:初识sed和gawk
《Linux命令行与shell脚本编程大全》 第十九章:正则表达式
《Linux命令行与shell脚本编程大全》 第二十章:sed进阶
《Linux命令行与shell脚本编程大全》 第二十一章:gawk进阶
《Linux命令行与shell脚本编程大全》 第二十二章:使用其他shell

第四部分:高级shell脚本编程主题
《Linux命令行与shell脚本编程大全》 第二十三章:使用数据库
《Linux命令行与shell脚本编程大全》 第二十四章:使用Web
《Linux命令行与shell脚本编程大全》 第二十五章:使用E-mail
《Linux命令行与shell脚本编程大全》 第二十六章:编写脚本实用工具
《Linux命令行与shell脚本编程大全》 第二十七章:shell脚本编程进阶

 

第二十一章:gawk进阶

 

使用变量

gawk支持两种类型的变量:

内建变量

自定义变量

内建变量

字段和数据行分割符变量

使用美元符号($)和数据字段在数据行中位置对应的数值来引用该数据行中的字段。

比如,要引用数据行中的第二个字段就使用$2

gawk数据字段和数据行变量

变量 描述
FIELDWIDTHS 由空格分隔开的定义了每个数据字段确切宽度的一列数字
FS 输入字段分割符
RS 输入数据行分割符
OFS 输入字段分隔符
ORS 输入数据行分隔符

OFS默认值为空格

$ cat column_data.txt
1987-06-05
$ gawk 'BEGIN{FS="-"} {print $1,$2,$3}' column_data.txt 
1987 06 05
$ gawk 'BEGIN{FS="-";OFS=":"} {print $1,$2,$3}' column_data.txt 
1987:06:05

一旦设置了FIELDWIDTHS,FS就会失效

一旦设置了FIELDWIDTHS值,就不可再更改

下面演示一下RS

假设我们有一份联系人名单,每个联系人之间用空行分割,格式如下

$ cat contacts 
Name1
Addr1
ZipCode1
Tele1

Name2
Addr2
ZipCode2
Tele2

Name3
Addr3
ZipCode3
Tele3

下面我们想读取姓名与电话。

默认情况下,gawk以换行符为行分隔符,这里我们可以使用空作为行分隔符。这样做的结果就是,使得每一个联系人作为单独的“一行”。然后我们再把字段分隔符设置为换行符,这样就可以提取我们所需要的内容了。

$ gawk 'BEGIN{FS="\n";RS=""} {print $1,$4}' contacts 
Name1 Tele1
Name2 Tele2
Name3 Tele3

数据变量

变量 描述
ARGC 当前命令行参数个数
ARGIND 当前文件在ARGV中的位置
ARGV 包含命令行参数的数组
CONVFMT 数字的转换格式(参见print语句);默认值为%.6 g
ENVIRON 当前shell环境变量及其值组成的关联数组
ERRNO 当读取或关闭输入文件发生错误时的系统错误号
FILENAME 用作gawk输入数据的数据文件的文件名
FNR 当前数据文件中的数据行数
IGNORECASE 设成非0值时,忽略gawk命令中出现的字符串的字符大小写
NF 数据文件中的字段总数
NR 已处理的输入数据行数目
OFMT 数字的输出格式;默认值为%.6 g
RLENGTH 由match函数所匹配的子字符串的长度
RSTART 由match函数所匹配的子字符串的起始位置

在gawk中引用gawk变量的时候,不需要美元符号

$ gawk 'BEGIN{print ARGC,ARGV[0],ARGV[1]}' contacts
2 gawk contacts

上面命令中共两个参数,gawk以及contacts

注意:gawk后的脚本不算参数

我们可以通过如下方式获取系统环境变量,既而在gawk中使用。

$ gawk 'BEGIN{print ENVIRON["HOME"]}' 
/home/su1216

我们可以通过如下方式来指定最后一个字段

$ gawk 'BEGIN{FS=":"; OFS=":"} {print $1,$NF}' /etc/passwd
root:/bin/bash
daemon:/bin/sh
bin:/bin/sh
sys:/bin/sh
......

注意:这里gawk先把NF计算出来,然后再执行$number,而不是像shell中把$NF视为对NF变量的引用。

下面看一下FNR与NR的区别

$ gawk 'BEGIN{FS="\n";RS=""} {print $1,"FNR="FNR, "NR="NR}' contacts contacts 
Name1 FNR=1 NR=1
Name2 FNR=2 NR=2
Name3 FNR=3 NR=3
Name1 FNR=1 NR=4
Name2 FNR=2 NR=5
Name3 FNR=3 NR=6

如果只使用一个数据文件作为输入,那么FNR与NR则一致。

处理第二个文件时,FNR变量被重置。

自定义变量

在脚本中给变量赋值

同shell中的变量赋值类似:

$ gawk '
> BEGIN{
> test="This is a test."
> print test
> test="Test again."
> print test
> }'
This is a test.
Test again.

还可以在其中直接进行数学运算

$ gawk '
BEGIN{
x=1                   
print "x="x
x=(x+1)**2
print "x="x
}'
x=1
x=4

可以直接进行求余(%)和方幂(**或者^)运算

在命令行上给变量赋值

可以在gawk脚本之外给gawk中变量赋值

$ cat gawk_script
BEGIN{FS=":"}{print $n}

上面是一个普通的gawk脚本,其中使用了变量n,但是并没有为其进行初始化。

$ gawk -f gawk_script n=1 /etc/passwd
root
daemon
bin
......

但是这个变量在BEGIN中是无效的,如果想在BEGIN中生效,需要使用-v选项。

$ gawk -v n=1 -f gawk_script /etc/passwd

 

处理数组

gawk使用关联数组来提供数组功能,它的索引可以是任意文本字符串。

定义数组变量

$ gawk '
> BEGIN{test["a"]="a"
> print test["a"]
> }'
a

遍历数组变量

可以使用for语句:

for (var in array)
{
    statements
}

例如:

$ gawk '
> BEGIN {
> test["a"]="a1"
> test["b"]="b2"
> test["c"]="c3"
> for (var in test)
> {
>     print var,test[var]
> }
> }'
a a1
b b2
c c3

删除数组变量

delete array[index]

$ gawk '
> BEGIN {
> test["a"]="a1"
> test["b"]="b2"
> test["c"]="c3"
> delete test["b"]
> for (var in test)
> {
>     print var,test[var]
> }
> }'
a a1
c c3

 

使用模式

BEGIN和END是用来在读取数据流之前或之后执行命令的特殊模式。

正则表达式

正则表达式必须出现在它要控制的程序脚本的左花括号前:

$ gawk '/Name[0-9]/{print $0}' contacts 
Name1
Name2
Name3

匹配操作符(matching operator)

匹配操作符允许将正则表达式限定在数据行中的特定数据字段。匹配操作符是波浪线(~)。需要一起指定匹配操作符、数据字段变量以及正则表达式:

$ gawk 'BEGIN{FS=":"} $1 ~ /sys/{print $0}' /etc/passwd
sys:x:3:3:sys:/dev:/bin/sh
syslog:x:101:103::/home/syslog:/bin/false

这里$1表示第一个字段,也就是说,打印出第一个字段中含有sys字样的行

可以使用!~来过滤没有满足正则表达式的字符串。

$ gawk 'BEGIN{FS=":"} $1 !~ /[aeiou]/{print $0}' /etc/passwd
sys:x:3:3:sys:/dev:/bin/sh
sync:x:4:65534:sync:/bin:/bin/sync
lp:x:7:7:lp:/var/spool/lpd:/bin/sh
gdm:x:113:120:Gnome Display Manager:/var/lib/gdm:/bin/false
sshd:x:115:65534::/var/run/sshd:/usr/sbin/nologin

数学表达式

可以使用下面几种形式:

x == y

x <= y

x < y

x > y

x >= y

这里不仅局限于数值比较,也可以作用在字符串上。

$ gawk 'BEGIN{FS=":"} $4 == 0{print $0}' /etc/passwd
root:x:0:0:root:/root:/bin/bash
$ gawk 'BEGIN{FS=":"} $1 == "sys"{print $0}' /etc/passwd
sys:x:3:3:sys:/dev:/bin/sh

 

结构化命令

if语句

语句格式:

if(condition)
    statement

if(condition) statement

if(condition){
    statements
}

if(condition){
    statements
}else{
    statements
}

if(condition) statement1; else statement2

while语句

语句格式:

while(condition){
    statements
}

do-while语句

语句格式:

do
{
    statements
} while (condition)

for语句

gawk支持C风格的for循环

语句格式:

for(variable assignment; condition; iteration process)

 

格式化打印

printf命令格式:

printf "format string", var1, var2 ...

gawk程序会将每个格式化指定符作为命令中列出的每个变量的占位符使用。第一个格式化指定符会匹配列出的第一个变量,第二个会匹配第二个变量,依此类推。

格式化指定符采用如下格式:

%[modifier]control-letter

其中control-letter指明显示什么类型数据值的单字符码,而modifier定义了另一个可选的格式化特性。

格式化指定符的控制字母

控制字母 描述
c 将一个数作为ASCII字符显示
d 显示一个整数值
i 显示一个整数值(跟d一样)
e 用科学记数法显示一个数
f 显示一个浮点值
g 用科学记数法或浮点数中较短的显示
o 显示一个八进制值
s 显示一个文本字符串
x 显示一个十六进制值
X 显示一个十六进制值,但用大写字符A-F

除了控制字母外,还有3种修饰符可以用来进一步控制输出。

width:指定了输出字段最小宽度的数字值。如果短于这个值,printf会向右对齐,并用空格来填充这段空间。如果输出比指定的宽度还要长,它就覆盖width值。

prec:指定了浮点数中小数点后面位数的数字值,或者文本字符串中显示的最大字符数。

-(减号):向格式化空间中放入数据时采用左对齐。

printf每打印一次,不会自动换行。

$ cat numbers 
1 2 3
123 456 789
172 245 946

$ gawk '{
> total = 0
> for (i = 1; i < 4; i++)
> {
>     total += $i
> }
> avg = total/3
> printf "Average: %5.1f\n",avg
> }' numbers
Average:   2.0
Average: 456.0
Average: 454.3

上面指定了显示浮点数,输出最小宽度是5,保留小数后一位,右对齐。

 

内建函数

gawk数学函数

函数 描述
atan2(x,y) x/y的反正切,x和y以弧度为单位
cos(x) x的余弦,x以弧度为单位
exp(x) x的指数函数
int(x) x的整数部分,取靠近0一侧的值
log(x) x的自然对数
rand() 比0大比1小的随机浮点值
sin(x) x的正弦,x以弧度为单位
sqrt(x) x的平方根
srand(x) 为计算随机数指定一个种子值

除了标准函数外,gawk还支持一些按位操作数据的函数

and(v1, v2):v1和v2的按位与运算

compl(val):val的补运算

lshift(val, count):将值val左移count位

or(v1, v2):v1和v2的按位或运算

rshift(val, count):将值val右移count位

xor(v1, v2):执行值v1和v2的按位异或运算

 

gawk字符串函数

函数 描述
asort(s [, d]) 将数组s按数据元素值排序。索引值会被替换成表示新的排序顺序的连续数字。如果指定了d,则排序后的数组回存储在数组d中
asorti(s [, d]) 将数组s按索引值排序。生成的数组会将索引值作为数据元素值,用连续数组索引来表明排序顺序。如果指定了d,排序后的数组回存储在数组d中
gensub(r, s, h [, t]) 查找变量$0或目标字符串t(如果提供了的话)来匹配正则表达式r。如果h是一个以g或者G开头的字符串,就用s替换掉匹配的文本。如果h是一个数字,它表示要替换掉第几处r匹配的地方
gsub(r, s, [, t]) 查找变量$0或目标字符串t(如果提供了的话)来匹配正则表达式r。如果找到了,就全部替换成字符串s
index(s, t) 返回字符串t在字符串s中的索引值,如果没找到的话,返回0
length([s]) 返回字符串s的长度,如果没有指定的话,返回$0的长度
match(s, r [, a]) 返回字符串s中正则表达式r出现位置的索引。如果指定了数组a,它会存储s中匹配正则表达式的那部分
split(s, a [, r]) 将s用FS字符或正则表达式r(如果指定了的话),分开放到数组a中。返回字段的总数
sprintf(format, variables) 用提供的format和variables返回一个类似于printf输出的字符串
sub(r, s [, t]) 在变量$0或目标字符串t中查找正则表达式r的匹配。如果找到了,就用字符串s替换掉第一处匹配
substr(s, i [, n]) 返回s中从索引值i开始的n个字符组成的子字符串。如果未提供n,则返回s剩下的部分
tolower(s) 将s的所有字符转换成小写 
toupper(s) 将s的所有字符转换成大写 

 

gawk的时间函数

函数 描述
mktime(datespec) 将一个YYYY MM DD HH MM SS [DST]格式置顶的日期转换彻骨时间戳(时间戳指:自1970-01-01 00:00:00 UTC到现在,以秒为单位的计数,通常称epoch time)
strftime(format [, timestamp]) 将当前时间的时间戳huotimestamp(如果提供了的话)转化成用shell函数格式date()的格式化日期
systime() 返回当前时间的时间戳(同上面的时间戳)

 

自定义函数

定义函数

必须使用function关键字

function name([variables])
{
    statements
}

可以使用return语句返回值

使用自定义函数

定义函数时,必须在所有代码块之前,包括BEGIN

$ gawk '
> function test(v1){
>     print v1
> }
> BEGIN{
> test("abc")
> }
> '
abc

使用函数库

1.首先需要创建一个存储gawk函数的文件:

$ cat gawk_lib
function test(v1){
    print v1
}

function add(){
    print $1+$2+$3
}

2.然后通过使用-f选项来指定函数库即可:

$ cat gawk_lib_test
BEGIN{
    FS=" "
}

{
    add()
}


$ gawk -f gawk_lib -f gawk_lib_test numbers 
6
1368
10363

 

 

 

 

 

转贴请保留以下链接

本人blog地址

http://su1216.iteye.com/

http://blog.csdn.net/su1216/

2
2
分享到:
评论

相关推荐

Global site tag (gtag.js) - Google Analytics