Linux Shell编程之sed编辑器&gawk程序


sed和gawk介绍
知识体系:
#使用文本文件
#探索sed
#探索gawk
shell脚本可以把处理文本中包含的所有类型的数据这样的普通任务自动化。然而,只使用shell脚本命令处理文本文件的内容却有些麻烦。如果要 在shell脚本中进行任何类型的数据处理,就要熟悉linux中现有的sed和gawk工具了。因为这两个命令行编辑器能够方便地格式化、插入、修改和删除文本元素。

1、文本处理
1.1、sed编辑器
sed编辑器称为流编辑器(stream editor),能根据在vim、vi等编辑器处理数据之前事先提供的规则集编辑数据流。它每次从输入读取一行数据,将该数据与所提供的编辑器命令进行匹配,根据命令修改数据流中的数据,然后将新数据输出到STDOUT。
使用sed命令格式:
sed option xxx(script file)
options参数允许自定义sed命令的行为,如下表:
***********************************************************
  选项    描述
-e script 将脚本中指定的命令添加到处理输入时执行的命令中
-f file  将文件中指定的命令添加到处理输入时执行的命令中
-n  不需要为每个命令产生输出,但要等待打印命令
***********************************************************
1.1.1、在命令行中定义编辑器命令
默认情况下,sed编辑器将指定的命令应用于STDIN输入流,这就允许将数据直接管道传送给sed编辑器处理,如下例子:
[root@www.bkjia.com ~]# echo "welcome to tencent" | sed 's/tencent/bkjia/'
welcome to bkjia
该例在sed编辑器中使用了s命令,表示说第二个文本字符替换第一个两个斜杠之间的文本字符,如上通过bkjia替换了tencent。
当然,如上只是编辑了一行数据,在一个数据文件中也可以通过sed处理:
[root@www.bkjia.com ~]# cat testfile
welcome to http://www.bkjia.com
welcome to http://www.bkjia.com
welcome to http://www.bkjia.com
[root@www.bkjia.com ~]# sed 's/blog/6688.cc/' testfile
welcome to http://www.6688.cc
welcome to http://www.6688.cc
welcome to http://www.6688.cc
或者通过cat借助管道查看:
[root@www.bkjia.com ~]# cat testfile | sed 's/blog/6688.cc/'
welcome to http://www.6688.cc
welcome to http://www.6688.cc
welcome to http://www.6688.cc
sed命令执行与返回数据几乎同时进行,但是sed编辑器并不修改文本文件中的数据,它只是把文本内容修改后发送到STDOUT,原文本文件没有改动过。
[root@www.bkjia.com ~]# cat testfile
welcome to http://www.bkjia.com
welcome to http://www.bkjia.com
welcome to http://www.bkjia.com
1.1.2、在命令行中使用多个编辑器命令
要从sed命令行执行多个命令,只需要使用-e选项:
[root@www.bkjia.com ~]# sed -e 's/blog/www/;s/bkjia/linxidc/' testfile
welcome to http://www.linxidc.com
welcome to http://www.linxidc.com
welcome to http://www.linxidc.com
两个命令同时应用于文件中的每一行数据,命令必须使用分号隔开。
当然,也可以使用此提示符,而不用分号分隔命令:
[root@www.bkjia.com ~]# sed -e '
> s/blog/www/
> s/bkjia/wzp/' testfile
welcome to http://www.bkjia.net
welcome to http://www.bkjia.net
welcome to http://www.bkjia.net
这里需要注意的是:要在后单引号出现的这一行完成整个命令,因为bash检测到后引号后就处理命令。
1.1.3、从文件读取编辑器命令
如果说,有太多的sed命令要处理,那么可以将他们保存在一个独立的文件中,然后在使用sed命令时候使用-f选项指定文件,如下例:
[root@www.bkjia.com ~]# cat script24
s/blog/www/
s/bkjia/idcfree/
这里不需要使用分号和单引号了,sed编辑器将每一行视为单独一个命令。
[root@www.bkjia.com ~]# sed -f script24 testfile
welcome to http://www.idcfree.com
welcome to http://www.idcfree.com
welcome to http://www.idcfree.com
通过调用script24这个预先指定好的文件就可以实现数据的处理。

1.2、gawk程序
尽管sed编辑器是动态修改文本文件的便利工具,但它也有自己的局限性,这个时候就可以借助更高级、能够提供类似于编程环境的工具,它允许修改和组织文件中的数据。
gawk程序是unix中原awk程序的GNU版本,它提供一种编程语言而不仅仅是编辑器命令。
1.2.1、gawk命令格式
gawk options xxx(program file)
如下是gawk程序的可用选项:
***********************************************************
选项   描述
-F fs  指定描绘一行中数据字段的文件分隔符
-f file  指定读取程序的文件名
-v var=value  定义gawk程序中使用的变量和默认值
-mf N  指定数据文件中要处理的字段的最大数目
-mr N  指定数据文件中的最大记录大小
-W keyword 指定gawk的兼容模式或警告级别
***********************************************************
1.2.2、自命令行读取程序脚本
gawk程序脚本由左大括号和右大括号定义,脚本命令必须放置在两个大括号之间,如下载命令行上指定的一个简单gawk程序脚本:
[root@www.bkjia.com ~]# gawk '{print "hello world!"}'
改程序定义了一个print命令才执行打印功能,将文本hello world!输出到STDOUT。然而,执行本命令不会发生任何显示信息。因为命令行中没有定义文件名,所以gawk程序要从STDIN获取数据,比如你随意输入任何内容,按回车键既可以实现print功能:
[root@www.bkjia.com ~]# gawk '{print "hello world!"}'
try to test and enter
hello world!
test again
hello world!
同sed编辑器完全一样,gawk程序对数据流中可用的每一行文本执行程序脚本。由于本程序脚本设定为显示固定的文本字符串,所以无论数据流中输入什么,都得到相同的输出。如果要结束gawk程序,必须发送信号说明数据流已经结束。bash shell提供了生成end-of-file(EOF)字符的组合键来发送结束信号。在bash中,Ctrl+D组合键生成EOF字符。
1.2.3、使用数据字段变量
gawk的主要功能之一就是处理文本文件中数据的能力,它通过自动将变量分配给每行中的每个数据元素实现这一功能。默认情况下,gawk将下面的变量分配给在文本行中检测到的每个数据字段:
* $0表示整行文本;
* $1表示文本行中的第一个数据字段;
* $2表示文本行中的第二个数据字段;
* $n表示文本行中的第n个数据字段;
各个数据段是根据文本行中的字段分隔符(默认是空格)确定的,如下通过gawk程序读取文本文件的数据段:
[root@www.bkjia.com ~]# cat test1
one line of test file
two line of test file
three  line of test file //(故意在three后面留两个空格)
[root@www.bkjia.com ~]# gawk '{print $1}' test1
one
two
three
通过$1字段变量即可显示每行文本的第一个字段;
[root@www.bkjia.com ~]# gawk '{print $2}' test1
line
line
line
你会发现,上面两个空格都被视为一个分隔符了,即把第二个字段显示出来。
当我们要修改默认的分隔符的时候可以使用-F选项,比如把分隔符改成冒号来读取/etc/passwd文件:
[root@www.bkjia.com ~]# tail -3 /etc/passwd
webalizer:x:67:67:Webalizer:/var/www/usage:/sbin/nologin
sabayon:x:86:86:Sabayon user:/home/sabayon:/sbin/nologin
mysql:x:27:27:MySQL Server:/home/mysql:/sbin/nologin
我们取最后三行来看,我们知道/etc/passwd就是以冒号来分隔每个字段的,所以我们要通过gawk查看指定某些字段时候就必须通过-F选项修改默认分隔符为冒号:
[root@www.bkjia.com ~]# tail -3 /etc/passwd | gawk -F: '{print $1,$6,$7}'
webalizer /var/www/usage /sbin/nologin
sabayon /home/sabayon /sbin/nologin
mysql /home/mysql /sbin/nologin
这样我们就把第一、第六、第七个字段显示出来了。
1.2.4、在程序脚本中使用多个命令
有时候我们需要在命令行指定的脚本中使用多个命令,只需要在各命令之间加一个分号:
[root@www.bkjia.com ~]# echo "welcome to bkjia" | gawk '{$3="bbs.bkjia"; print $0}'
welcome to bbs.bkjia
第一个命令为$3字段指定为bbs.bkjia,第二个命令为打印整个数据字段。
当然,这里也可以通过此提示符每次输入一行程序脚本命令:
[root@www.bkjia.com ~]# gawk '{
> $3="bbs.bkjia"
> print $0}'
welcome to bkjia
welcome to bbs.bkjia
welcome to netease
welcome to bbs.bkjia
当把gawk '{ $3="bbs.bkjia"; print $0}'写好后,输入的任何内容,第二个字段都被修改成bbs.bkjia
如果要结束程序,可以使用ctrl+d组合键发送结束信号。
1.2.5、从文件读取程序
同sed编辑器一样,gawk编辑器允许将程序保存在文件中并在命令行中引用:
[root@www.bkjia.com ~]# cat script24
{ print $5 "'s userrid is " $1}
[root@www.bkjia.com ~]# tail -3 /etc/passwd | gawk -F: -f script24
Webalizer's userrid is webalizer
Sabayon user's userrid is sabayon
MySQL Server's userrid is mysql
当然,被调用的文件可以指定多个命令,则使得每行放置一个命令而不需要使用分号:
[root@www.bkjia.com ~]# cat script25
{
text="'s userid is"
print $5 text $1
}
[root@www.bkjia.com ~]# tail -3 /etc/passwd | gawk -F: -f script25
Webalizer's userid iswebalizer
Sabayon user's userid issabayon
MySQL Server's userid ismysql
我们可以看到得到的结果是一样的,不过有点需要注意的是gawk程序不像shell脚本不需要使用美元符号引用变量值,所以直接用print命令显示结果。
1.2.6、在处理数据之前运行脚本
gawk程序还允许指定运行脚本的时间。默认情况下,gawk从输入读取一行文本,然后执行程序脚本处理文本行中的数据。但有时需要在处理数据之前运行脚本,就必须使用BEGIN关键字了,如下:
[root@www.bkjia.com ~]# gawk 'BEGIN {print "hello world!"}'
hello world!
print命令将在读取数据之前显示文本,不过它在显示该文本之后迅速退出而不等待数据输入。
1.2.7、在处理数据之后运行脚本
与BEGIN关键字类似,END关键字允许指定在读取数据之后gawk执行的程序脚本:
[root@www.bkjia.com ~]# gawk 'BEGIN {print "hello world!" }{print $0} END {print "goodbye"}'
hello world!
this is a test
this is a test
i would enter ctrl+d
i would enter ctrl+d
goodbye
执行程序开始就print出hello world!字符,接着输入的任何数据都通过$0回显一次,当我ctrl+d结束程序的时候,程序就print出goodbye字符。所以,通过这种方法非常适合创建数据报告。

  • 1
  • 2
  • 3
  • 下一页

相关内容