加入收藏 | 设为首页 | 会员中心 | 我要投稿 通化站长网 (https://www.0435zz.com/)- 科技、建站、经验、云计算、5G、大数据,站长网!
当前位置: 首页 > 教程 > 正文

Linux Shell 编程之gawk分析

发布时间:2021-12-05 15:15:34 所属栏目:教程 来源:互联网
导读:awk 简史: The name awk comes from the initials of its designers: A lfred V. Aho, Peter J. W einberger, and Brian W. K ernighan. The original version of awk was written in 1977 at ATT Bell Laboratories. gawk 简史: Paul Rubin wrote gawk in

awk 简史:
 
The name awk comes from the initials of its designers: A lfred V. Aho, Peter J. W einberger, and Brian W. K ernighan. The original version of awk was written in 1977 at AT&T Bell Laboratories.
 
gawk 简史:
 
Paul Rubin wrote gawk in 1986. Jay Fenlason completed it, with advice from Richard Stallman. John Woods contributed parts of the code as well. In 1988 and 1989, David Trueman, thoroughly reworked gawk for compatibility with the newer awk.
 
gawk 是 awk 的 GNU 版本。是一个功能更加强大的具有编程扩展性的工具。
 
gawk 的命令格式
 
gawk options
 
program
 
 
 
file
 
 
简单的对 options 做个介绍:
 
 
 
-F fs : 指定航中分割数据字段的字段分隔符
 
 
-f file: 指定读取程序的文件名。多行命令可以放在一个文件以便复用
 
 
-v var=value:   指定 gawk 程序中一个变量以及其默认值
 
 
-mf N:  指定要处理的数据文件中的最大字段数
 
 
-mr N:  指定数据文件中的最大数据行数
 
 
-W keyword: 指定 gawk 的兼容模式或警告等级
 
 
gawk 的命令编程
gawk 的中心是其命令,可以有两种方式来调用命令
 
命令行的调用方式;
 
将多行命令编写在文件的调用方式
 
命令行的调用方式:
 
[root@CentOS00 _data]
 
# gawk '{print "hello, world!"} '
 
_
 
 
要注意的是两点:
'{}' 成为 gawk 的固定格式,{} 是放置 gawk 命令的地方,而'' 是将命令当做字符串与其他选项或参数字符串隔离的分隔符。
 
 
[root@centos00 _data]
 
# gawk 'print "hello, world!" '
 
gawk: cmd. line:
 
1
 
:
 
print
 
 
 
"hello, world!"
 
 
 
gawk: cmd. line:
 
1
 
: ^ syntax error
 
 
 
[root@centos00 _data]
 
# gawk {print "hello, world!"}
 
 
bash: !"}: event not found
 
[root@centos00 _data]
 
#
 
 
gawk 的默认从标准输入流来读文本,如果没有指定文本文件,那就等待标准输入流的输入:
 
 
[
 
root@
 
centos00 _data]# gawk
 
'{print "hello, world!"} '
 
 
this
 
 a hello world programm
 
hello, world!
 
 
多条命令也可以写在一行中处理,使用“;”分隔符即可:
 
 
[root
 
@centos
 
00 _data]# gawk -F:
 
'{ $6 = $1 ":" $6 ; print $1 "'
 
 
's home director is " $6 } '
 
 /etc/passwd
 
roots home director
 
is
 
 root:/root
 
bins home director
 
is
 
 bin:/bin
 
daemons home director
 
is
 
 daemon:/sbin
 
adms home director
 
is
 
 adm:/
 
var
 
/adm
 
lps home director
 
is
 
 lp:/
 
var
 
/spool/lpd
 
syncs home director
 
is
 
 
 
sync
 
:/sbin
 
 
对单引号"'"做转义的时候,使用两次单引号即可,而不是使用"".
 
gawk 的功能也是对每行输入做处理。
 
将多行命令编写在文件的调用方式
 
[root@centos00 _data]
 
# gawk -F: -f getUserDirectory.awk /etc/passwd
 
 
 
[root@centos00 _data]
 
# cat getUserDirectory.awk
 
{
 
print
 
 $
 
1
 
 
 
"'s home directory is "
 
 $
 
6
 
 }
 
[root@centos00 _data]
 
# gawk -F: -f getUserDirectory.awk /etc/passwd
 
root
 
's home directory is /root
 
bin'
 
s home directory
 
is
 
 /bin
 
daemon
 
's home directory is /sbin
 
adm'
 
s home directory
 
is
 
 /var/adm
 
lp
 
's home directory is /var/spool/lpd
 
 
 
多行命令写在文件中:
 
 
[root@centos00 _data]
 
# cat getUserDirectory.awk
 
{$6 = $1
 
":"
 
 $6 }
 
{
 
print
 
 $1
 
"'s home directory is "
 
 $6 }
 
[root@centos00 _data]
 
# gawk -F: -f getUserDirectory.awk /etc/passwd
 
root
 
's home directory is root:/root
 
bin'
 
 
s
 
 home directory is bin:
 
/bin
 
daemon's home directory is daemon:/sbin
 
 
依然是用{} 来引用命令,但不需要''来分割命令字符串了
 
1 ,2, 3 ,n 是标识被-F 指定的字段分隔符分割的字段值。
 
$1 就是输入文件中的第一栏
 
gawk 的重头戏 - “命令”武器库
编程思路大家都没大问题,针对 gawk 首先要了解的是他的武器库,到底藏了哪些宝贝
 
 
AK-47,可靠精良,擅长短距离横扫;
 
M16,轻便成熟,火力猛;
 
沙漠之鹰,更符合随身细带的要求。
 
 
因此依据作战规模,我们需要选好手上的武器:
 
循环
 
条件
 
变量
 
操作函数
 
变量
变量又可分为“内建变量”和“自定义变量”
 
内建变量
 
举个例子来说明:
 
 
[root
 
@centos
 
00 _data]# gawk -F:
 
'{ $6 = $1 ":" $6 ; print $1 "'
 
 
's home director is " $6 } '
 
 /etc/passwd
 
roots home director
 
is
 
 root:/root
 
bins home director
 
is
 
 bin:/bin
 
daemons home director
 
is
 
 daemon:/sbin
 
 
这里的 6 就 是 内 建 变 量 , 看 得 出 来 , 字 段 索 引 内 建 变 量 需 要 用来标记。而 6 的 6 就 是 指 文 本 文 件 中 的 第 6 列 , 以 此 类 推 ,7 就是第 7 列,且取出来之后,可以对 6 ,7 做变更。
 
那么问题就来了:
 
是否能将内建变量取出来的值,做修改,再传回源文件做保存呢?
 
除了 $n ( n 指代 1,2,3,4,5,6…等自然数)之外,还有一些内建变量:
 
FS: 输入字段分隔符
 
RS: 输入数据行分隔符
 
OFS: 输出字段分隔符
 
ORS: 输出数据行分隔符
 
 
[root@centos00 _data]
 
# echo '32:31:33'|gawk 'BEGIN {FS=
 
":"
 
;OFS=
 
"|"
 
} {print $1,$2,$3}'
 
 
32
 
|
 
31
 
|
 
33
 
 
ENVIRON 也是比较有意思的内建变量用法:
 
 
[root@centos00 _data]
 
# gawk 'BEGIN{ print ENVIRON["PATH"] }'
 
/root/perl5/bin:/usr/lib64/qt-3.3/bin:/home/huangyun/perl5/bin:/usr/
 
local
 
/bin:
 
 
 
更多 gawk 内建的变量,参考文档:
 
ftp:
 
//ftp.gnu.org/old-gnu/Manuals/gawk-3.0.3/html_chapter/gawk_11.html
 
https:
 
//www.gnu.org/software/gawk/manual/gawk.html#SEC_Contents
 
 
自定义变量
 
无法想象只有内建变量的编程世界会是怎么样,大概会像少了插件那样去用 visual studio code 吧,很无助。所以自定义变量是肯定会支持的
 
 
[root@centos00 _data]
 
# gawk '{Greetings="hello world";print Greetings}'
 
d
 
hello world
 
^C
 
[root@centos00 _data]
 
# gawk 'BEGIN{Greetings="hello world";print Greetings}'
 
hello world
 
[root@centos00 _data]
 
#
 
 
Greetings 是自定义的变量,第一个例子很有趣,没有BEGIN 指令,gawk 始终是在等待输入。
 
自定义变量之数组
 
数组在 gawk 中的使用,更像是 K-V 对:
 
 
[root@centos00 _data]
 
# gawk 'BEGIN{
 
Prize[
 
"One"
 
]=
 
"house"
 
Prize[
 
"Two"
 
]=
 
"iphoneX"
 
 
for
 
( prize
 
in
 
 Prize)
 
{
 
  
 
print
 
 Prize[prize]
 
}
 
}
 
'
 
iphoneX
 
house
 
 
 
变量在程序结构中是区分大小写的!是区分大小写的!是区分大小写的!
 
结构化命令 (条件,循环)
 
 
#
 
if
 
 条件:
 
 
if
 
(condition)
 
 statement
 
 
 
 
# while 循环
 
 
while
 
(condition)
 
{
 
    statements
 
}
 
 
 
#
 
do
 
 
 
while
 
 循环
 
 
do
 
{
 
    statements
 
}
 
 
while
 
(condition)
 
 
 
 
# for 循环
 
 
# c语言风格
 
 
for
 
(i=1;i<4;i++)
 
{
 
    total +=
 
$i
 
}
 
 
# python 式
 
 
for
 
( prize
 
in
 
 Prize)
 
{
 
  
 
print
 
 Prize[prize]
 
}
 
 
已知每行字段总数可以用内建变量 NF 标识,据此可以打印出每个字段的值:
 
 
[root@centos00 _data]
 
# cat testData.txt
 
 
123
 
 
 
345
 
 
 
567
 
 
 
789
 
 
111
 
 
 
222
 
 
 
333
 
 
 
444
 
 
333
 
 
 
555
 
 
 
666
 
 
 
777
 
[root@centos00 _data]
 
# gawk '{for(i=1;i<=NF;i++){ print $i } }' testData.txt
 
 
123
 
 
345
 
 
567
 
 
789
 
 
111
 
 
222
 
 
333
 
 
444
 
 
333
 
 
555
 
 
666
 
 
777
 
[root@centos00 _data]
 
#
 
 
操作函数
跟变量一样,可分“内建函数”和“自定义函数”
 
内建函数参考文档即可,不需要太多的解释。
 
我们该关心的还是自定义函数。
 
自定义函数的格式
 
 
[root@centos00 _data]# gawk '
 
 
>
 
 
 
 
function
 
 getRand(myRand)
 
 
>
 
 
 {
 
 
>
 
 
 
 
print
 
 myRand*rand()
 
 
>
 
 
 }
 
 
>
 
 
 BEGIN{
 
 
>
 
 
 
 
print
 
 getRand(4)
 
 
>
 
 
 }
 
'
 
 
0.95115
 
[root@centos00 _data]#
 
 
所有的自定义函数一定是放在 BEGIN 之前,或者说程序的开头。
 
但马上就会有问题的是,函数必须重用。重复发明不必要的轮子,是低效的。因此 gawk 给出了函数库这个概念。
 
将所有的自定义函数归档到函数库中,在使用个别函数时候,只要引用这个库就可以了。相信 Java 朋友不陌生,Python 朋友简直是秒懂,就是库引用嘛!
 
 
[root@centos00 _data]
 
# cat funclib.awk
 
function myprint()
 
{
 
    
 
printf
 
 
 
"%-16s - %sn"
 
, $1, $4
 
}
 
function getRand(myRand)
 
{
 
    
 
print
 
 myRand*
 
rand
 
()
 
}
 
[root@centos00 _data]
 
# cat rand.awk
 
BEGIN{FS=
 
":"
 
}
 
{
 
    getRand(NF)
 
}
 
[root@centos00 _data]
 
# gawk -f funclib.awk -f rand.awk /etc/passwd
 
 
1.66451
 
 
2.03746
 
 
5.9207
 
 
1.06546

(编辑:通化站长网)

【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!