这两个工具能够极大简化需要进行的数据处理任务。

19.1 文本处理

能轻松实现自动格式化、插入、修改或删除文本元素的简单命令行编辑。

sed和gawk就具备上述功能

19.1.1 sed编辑器

被称为流编辑器

流编辑器会在编辑器处理数据之前预先提供的一组规则来编辑数据流。

sed根据命令来处理数据流中的数据。命令可以从命令行输入,也可以存储在一个命令文本文件中。

sed编辑器会执行下列操作:

1)一次从输入中读取一行数据

2)根据所提供的编辑命令匹配数据

3)按照命令修改流中的数据

4)将新的数据输出到STDOUT

sed将所有命令与一行数据匹配完毕后,就读取下一行重复这个过程。

sed命令格式如下:

sed options script file

选项允许修改sed命令的行为,可以使用的选项在下表:

选项        |  描述

-e script  |  在处理输入时,将script中指定的命令添加到已有的命令中

-f file       | 在处理输入时,将file中指定的命令添加到已有的命令中

-n            | 不产生命令输出,使用printf命令来完成输出

一般是单个命令,如果需要多个命令,加上-e选项,并用分号隔开,命令末尾和分号之间不能有空格。

1.在命令行定义编辑器命令

默认情况下,sed编辑器会将指定的命令应用到STDIN输入流上。这样可以直接将数据通过管道输入给sed命令处理

$echo “hahaha, I am xiaochongyong” | sed ‘s/xiaochongyong/Kobe Bryant/’

把xiaochongyong替换成了Kobe Bryant。

sed将结果发送到STDOUT

还可以这样修改指定文件中的数据:

$sed ‘s/dog/cat/’ my.txt  

// 将my.txt的dog换成cat输出。这样并不会改变my.txt.而是输出到了STDOUT

2. 使用多个编辑命令

需要用-e选项;

$sed –e ‘s/dog/cat/; s/red/yellow/’ my.txt

sed命令会将指定的每条命令应用到文本文件中的每一行上。

3. 从文件中读取编辑命令

需要用-f选项来指定文件。

sed会读取指定文件中命令,并且应用到数据文件中的每一行

比如:

file.sed中有

s/dog/cat/

s/red/blue/

s/xiao/yang/

可以这么用:

$sed –f file.sed my.txt.

窍门:可以用.sed作为sed脚本文件的扩展名

19.1.2 gawk程序

它提供了一种编程语言而不只是编辑器命令,在gawk编程语言中,可以做:

1)定义变量保存数据

2)使用算术和字符串操作符来处理数据

3)使用结构化编程的概念来为数据处理增加处理逻辑

4)通过提取数据文件中的数据元素,将其重新排列或格式化,生成格式化报告。

gawk程序的报告生成能力通常用来从大文本文件中提取数据元素,并将它们格式化成可读的报告。比如格式化日志文件,找出日志文件中的错误行。

1.gawk命令格式

gawk options program file

下面是可用选项的说明:

-F fs         指定行中划分数据字段的字段分隔符

-f file        从指定的文件中读取程序

-v var=value   定义一个变量var并设置默认值

-mf N        指定要处理的数据文件中的最大字段数

-mr N        指定数据文件中的最大数据行数

-w keyword   指定gawk的兼容模式或警告等级

它的强大之处在于程序脚本,可以写脚本来读取文本行中的数据,然后处理并显示数据,创建任何类型的输出报告。

2. 从命令行读取程序脚本

gawk程序脚本用一对花括号来定义。必须将脚本命令放到两个花括号{}中间。

比如:

$gawk ‘{print “hello, shell”}’

因为没有指定文件名,所以这个gawk程序会从STDIN接收数据,运行时会一直等待从STDIN输入的文本。

Ctrl+D会在bash中产生一个EOF字符,可以终止该程序。

3. 使用字段字段变量

它会自动给一行中的每个数据元素分配一个变量。

比如:

$0 表示整个文本行

$1 表示文本行中的第1个数据字段

$2 表示文本行中的第2个数据字段

$n 表示文本行中的第n个数据字段

例子:

$gawk ‘{print $2}’ data.txt    // 输出data.txt所有行的第2个数据字段

默认是用空格分隔的,也可以指定其他分隔符。

比如:

$gawk –F: ‘{print $1}’ /etc/passwd    // 输出/etc/passwd第一个字段,用冒号分隔的。

4. 在程序脚本中使用多个命令

命令中间放个分号就好了

$echo “My name is xcy” | gawk ‘{%2 = “age”; $4 = 23; print $0}’

注意:age两边需要双引号, =前后可以有空格,也可没有空格。

5. 从文件中读取程序

比如有个脚本test.gawk内容如下:

{print $1 “’s home is ” $6}

用法:

$gawk –F: -f test.gawk /etc/passwd

test.gawk内容还可以是这样:这样相当于指定了多条命令,每条命令分行放开就好了。

{

text=”’s home is ”

print $1 text $6

}

6. 在处理数据前运行脚本

gawk还允许指定程序脚本何时运行。

默认gawk会从输入中读取一行文本,然后针对该行的数据执行程序脚本。

有时候会需要在处理数据前运行脚本,BEGIN就是用来做这个的。

比如:

$gawk 'BEGIN {print "The test3 file:"} {print $0}' test3

高亮部分是命令,红字是BEGIN处理。BEGIN后面也是一段脚本,也需要用{}括起来。

7. 在处理数据后运行脚本

跟BEGIN蕾西,还可以指定在读取完数据后执行的脚本。

比如:

$gawk 'BEGIN {print "The test3 file:"} {print $0} END {print "The file End"} ' test3

红色是END指定的脚本。

例子:

文件ga.gawk:

  1 BEGIN {

  2         print "The latest list of users and shells"

  3         print "UserID \t Shell"

  4         print "--------- \t ---------"

  5         FS=":"

  6 }

  7

  8 {

  9         print $1 "      \t" $7

 10 }

 11

 12 END{

 13         print "This concludes the listing"

 14 }

用法:

$gawk –f ga.gawk /etc/passwd

运行一下效果,小惊喜哦。

19.2 sed编辑器基础

19.2.1 更多的替换选项

1. 替换命令语法:

s/pattern/replacement/flags

flags有四种选项:

数字:表明新文本将替换第几处模式匹配的地方。

g:替换所有匹配的文本

p:代表原先行的内容要打印出来

w file:将替换的结果写到文件中去

比如:

$sed ‘s/old/new/2’ data.txt    表示第2个old替换成new。

$sed ‘s/old/new/g’ data.txt    表示全部替换

$sed ‘s/old/new/p’ data.txt    会打印与替换命令中指定的模式匹配的行

$sed -n ‘s/old/new/p’ data.txt   -n 会禁止sed编辑器输出

$sed ‘s/old/new/w data.bak’ data.txt  w替换标记会产生同样的输出,不过会将输出保存到指定文件中。

sed编辑器的正常输出是在STDOUT中,而只有那些包含匹配模式的行才会保存在指定的输出文件中。(假如data.txt 有3行,第一行第三行有old,第二行没有,那么第二行不会保存在指定的输出文件中)。

2. 替换字符

有时会遇到不太方便在替换模式中使用的字符,比如/

比如,想用c shell替换/etc/passwd 中的bash shell,可以这么干:

$sed ‘s/\/bin\/bash/\/bin\/csh/’ /etc/passwd

//   大概就这格式:   s/new/old/

解决方法:运行用其他字符来作为替换命令中的字符串分隔符,比如感叹号。

$ sed ‘s!/bin/bash!/bin/csh!’ /etc/passwd

用其他的符号也可以,比如逗号。这样路径名就更容易理解和阅读了。

19.2.2 使用地址

默认命令会应用于所有的行,但是也可以将命令作用于特定行。

解决方法:行寻址。

有两种行寻址的方法:

1)已数字形式表示行区间

2)用文本模式来过滤出行

命令格式:

[address] command

也可以将特定地址的多个命令分组

[address] {

command1

command2

command3

}

1. 数字方式的行寻址

指定地址可以是单个行号,比如:

$sed ‘2s/old/new/’ data.txt    // 只替换第2行

也可以是起始行加逗号加结束行的一个区间内的行,比如:

$sed ‘2,4s/old/new/’ data.txt    // 替换2 - 4行

$sed ‘2,$s/old/new/’ data.txt    // 替换2 到结束行, $ 表示最后一行

2. 使用文本模式过滤器

允许指定文本模式来过滤出命令要作用的行。格式如下:

/pattern/command

必须用正斜线将要指定的pattern封起来。sed编辑会将该命令作用到包含指定文本模式的行上。

比如只修改包含xcy 的那一行:

$sed ‘/xcy/s/bash/csh/’ /etc/passed

红字相当于/pattern/,紫色字就是command

sed编辑器在文本模式中采用了一种称为正则表达式的特性来帮助你创建匹配效果更好的模式。就是上面的 pattern

3. 命令组合

还可以控制多条命令在指定行中运行。

比如:

$sed ‘2{s/old/new/; s/dog/cat/}’ data.txt

$sed ‘3,${s/old/new/; s/dog/cat/}’ data.txt

19.2.3 删除行

s命令是文本替换

d命令是删除行

比如:

$sed ‘d’ data.txt   // 删除指定行

$sed ‘2d’ data.txt   //  删除第2行

$sed ‘2,$d’ data.txt   // 删除2到最后一行

模式匹配特性也适用于删除命令:

$sed ‘/xcy/d’ data.txt  // 删除包含xcy 的行

不会真正在文件中删除,只是在sed命令输出中删除了。

19.2.4 插入和附加文本

sed编辑器允许向数据流插入和附加文本行

插入(insert):命令(i)会在指定行前增加一个新行

附加(append):命令(a)会在指定行后增加一个新行

它们不能在单个命令行上使用,你必须指定是要将行插入还是附加到另一行。

格式如下:

sed ‘[address]command\ new line’

比如:// 这里是插入到line 2的前一行

$echo “This is line 2” | sed ‘i\This is line 1’

或者: // 附加到 line 2的后一行

$echo “This is line 2” | sed ‘a\This is line 1’

要向数据流行内部插入或附加数据,必须要指明加在什么位置。

$sed ‘2a/this is append line’ data.txt

$sed ‘3i/this is append line’ data.txt

下面的例子是增加两行, this is insert line 2' data.txt 后面按回车,运行命令。

增加多行必须要对cherub或附加的新文本中的每一行使用反斜线,就像下面的this is insert line 1\

 

xcy@xcy-virtual-machine:~/shell/19zhang$ sed '1i\

this is insert line 1\

this is insert line 2' data.txt

this is insert line 1

this is insert line 2

This is line 1

This is line 2

This is line 3

This is line 4

xcy@xcy-virtual-machine:~/shell/19zhang$

19.2.5 修改行

修改(change)允许修改数据流中整行的内容,它跟插入附加的工作机制一样,必须在sed命令中单独指定新行

$sed ‘2c\This is change line.’ data.txt

$sed ‘2,3c\This is change line.’ data.txt    // 这个会用一行把2 3行替换了。

还可以用文本模式来寻址: 对包含line 3的地方进行修改。这个会修改多行。如果匹配到多行的话。

$sed ‘/line 3/c\This is change line.’ data.txt

19.2.6 转换命令

转换(transform)命令(y)是唯一可以处理单个字符的sed命令编辑器命令。

格式如下:

[address]y/inchars/outchars/

转换命令会对inchars和outchars值进行一对一的映射。

inchars的第一个字符会被转换成outchars的第一个字符

inchars的第二个字符会被转换成outchars的第二个字符

以此类推。

inchars和outchars的长度必须一致,否则会报错。

例子:

$sed ‘y/123/abc/’ data.txt   // 1->b  2->b  3->c

$sed ‘2,3y/123/abc/’ data.txt  // 还可以指定行

转换命令是一个全局命令,它会在文本行中找到的所有指定字符自动进行转换,而不会考虑它们出现的位置

19.2.7 回顾打印

有3个命令也能用来打印数据流中的信息:

p命令用来打印文本行

等号(=)命令用来打印行号

l(小写的L)用来列出行

1.打印行

$echo “This is test” | sed ‘p’

打印文件中的行,-n选项用来禁止sed编辑器的输出,

$sed –n ‘2,3/p’ data.txt

$sed –n ‘/line 2/p’ data.txt  // 匹配文本模式中的行

下面是一种复杂的用法,

xcy@xcy-virtual-machine:~/shell/19zhang$ sed -n '/3/{

> p

> s/line/new_line/p

> }' data.txt

This is line 3

This is new_line 3

xcy@xcy-virtual-machine:~/shell/19zhang$

先找到包含数字3的行,再输出,再将指定行的line替换成new_line并输出。输出同时显示了原来的行文本和新的行文本。

2.打印行号

$sed ‘=’ data.txt

还可以打印包含指定文本的内容和行号:打印包含line 3的行号和内容

xcy@xcy-virtual-machine:~/shell/19zhang$ sed -n '/line 3/{

> =

> p

> }' data.txt

3

This is line 3

xcy@xcy-virtual-machine:~/shell/19zhang$

3.列出行

l可以打印数据流中的文本和不可打印的ASCII字符。

$sed ‘l’ data.txt

行尾的换行符会用美元符代替。

19.2.8 使用sed处理文件

1.写入文件

w命令用来想文件写入行,格式如下:

[address]w filename

filename可以是相对路径,也可以是绝对路径,文件需要有写权限。

例子:

$sed ‘2,3w write.txt’ data.txt   // 读取2 3行,写入write.txt

$cat write.txt

$sed ‘/xiaochongyong/w write.txt’ data.txt   // 读取包含xiaochongyong的行,写入write.txt

$cat write.txt

2.从文件读取数据

读取(read)命令(r)允许你将一个独立文件中的数据插入到数据流中。

格式如下:

[address]f filename

在读取命令中使用地址区间,只能指定单独一个行号或文本模式地址,sed编辑器会将文件中的文本插入到指定地址后。

例子:

$sed ‘3r read.txt’ data.txt  // 将read.txt的数据插入到data.txt的第三行中

$sed ‘$r read.txt’ data.txt   // 在数据流的末尾添加文本

$sed ‘/xiaochongyong/r read.txt’ data.txt   // 还可以用文本匹配

还可以这么用:

xcy@xcy-virtual-machine:~/shell/19zhang$ sed '/line 2/{

> r read.txt

> d

> }' data.txt

This is line 1

This is read line 1

This is read line 2

This is read line 3

This is line 3

This is line 4

xcy@xcy-virtual-machine:~/shell/19zhang$

带下划线的是read.txt中的内容。

这个例子先找到包含line 2的行,然后读取read.txt中的内容,然后再删除原来包含line 2的那行。

19.3 小结

使用sed和gawk程序的关键在于如何使用正则表达式。正则表达式是为提取和处理文本文件中数据创建定制过滤器的关键。

《Linux命令行与shell脚本编程大全》第十九章 初识sed和gawk的更多相关文章

  1. 《Linux命令行与shell脚本编程大全》第二十一章 sed进阶

    本章介绍一些sed编辑器提供的高级特性. 21.1 多行命令 按照之前的知识,所有的sed编辑器命令都是针对单行数据执行操作的. 在sed编辑器读取数据流时,它会基于换行符的位置将数据分成行,一次处理 ...

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

    第二十七章:shell脚本编程进阶 监测系统统计数据 系统快照报告 1.运行时间 uptime命令会提供以下基本信息: 当前时间 系统运行的天数,小时数,分钟数 当前登录到系统的用户数 1分钟,5分钟 ...

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

    第二十三章:使用数据库 MySQL数据库 MySQL客户端界面 mysql命令行参数 参数 描述 -A 禁用自动重新生成哈希表 -b 禁用 出错后的beep声 -B 不使用历史文件 -C 压缩客户端和 ...

  4. 《Linux命令行与shell脚本编程大全》 第六章环境变量

    很多程序和脚本都通过环境变量来获取系统信息.存储临时数据和配置信息. 6.1 什么是环境变量: bash shell用一个叫环境变量(environment variable)的特性来存储有关shel ...

  5. 《Linux命令行与shell脚本编程大全》第十三章 更多的结构化命令

    本章讨论bash shell的循环命令for.while和until 13.1 for命令 重复执行一系列命令在编程中很常见. bash shell提供了for命令,允许你创建一个遍历一系列值的循环. ...

  6. 《Linux命令行与shell脚本编程大全》第十一章 构建基本脚本

    11.1使用多个命令 $date;who   //  命令列表,加入分号就可以,这样会依次执行.参见5.2.1节 注意区分$(date;who),这个是进程列表,会生成一个子shell来执行 Shel ...

  7. 《Linux命令行与shell脚本编程大全》 第三章 学习笔记

    第三章:基本的bash shell命令 bash程序使用命令行参数来修改所启动shell的类型 参数 描述 -c string 从string中读取命令并处理他们 -r 启动限制性shell,限制用户 ...

  8. 《Linux命令行与shell脚本编程大全》第十七章 创建函数

    可以将shell脚本代码放进函数中封装起来,这样就能在脚本中的任何地方多次使用它了. 17.1 基本的脚本函数 函数:是一个脚本代码块,可以为其命名并在代码中任何位置重用. 17.1.1 创建函数 有 ...

  9. 《Linux命令行与shell脚本编程大全》 第五章理解shell

    5.1 1. cat /etc/passwd 可以查看每个用户自己的默认的shell程序. 2.默认的交互shell会在用户登录某个虚拟控制台终端时启动. 不过还有另外一个默认的shell是/bin/ ...

  10. 《Linux命令行与shell脚本编程大全》 第七章理解Linux文件权限

    Linux沿用了Unix文件权限的方法,允许用户和组根据每个文件和目录的安全性设置来访问文件. 用户权限通过创建用户时分配的用户ID(UID)来跟踪的.每个用户有唯一的ID,但是登录时用的不是UID, ...

随机推荐

  1. (转)Java正则表达式的语法与示例

    转自:http://www.cnblogs.com/lzq198754/p/5780340.html 概要: Java正则表达式的语法与示例 | |目录 1匹配验证-验证Email是否正确 2在字符串 ...

  2. 如何用VS EF连接 Mysql,以及执行SQL语句 和存储过程?

    VS2013, MySQL5.7.18 , MySQL5.7.14 执行SQL语句: ztp_user z = new ztp_user(); object[] obj = new object[] ...

  3. .NET之父 - Anders Hejlsberg

    简介 安德斯·海尔斯伯格(Anders Hejlsberg,1960.12~),丹麦人,Turbo Pascal编译器的主要作者,Delphi和.NET之父! 安德斯·海尔斯伯格曾在丹麦技术大学学习工 ...

  4. Windows系统下Nginx的安装与配置

    Nginx是lgor Sysoev在2004年的时候为俄罗斯访问量第二大的rambler.ru站点设计开发的,发布至今,凭借开源的力量,已经接近成熟与完善.其功能丰富,可作为HTTP服务器,也可作为反 ...

  5. ip完整验证详情

    不想跳坑就看一下 之前一直不太会写正则表达式,很多要用到正则表达式的都直接百度,像上次要用正则表达式验证是否是合法的ip地址,然后就上网找,结果就是没找到一个对的,今天就为大家贡献一下,写个对的,并做 ...

  6. bootstrap 鼠标悬停显示

    1. <button type="button" rel="drevil" data-content="报名截止时间:'+time+'" ...

  7. Python 由__dict__和dir()引发的一些思考

    关于__dict__和dir()的区别和作用请参考这篇文章:http://blog.csdn.net/lis_12/article/details/53521554 说下我当时遇到的问题: class ...

  8. 聊聊 Material Design 里,阴影的那些事儿!

    当你的设计师要求你在某个 View 上增加阴影效果,那你只需要认真阅读本文,阴影的问题就不再是问题. 一.前言 设计师的世界,与常人不同,有时候想要扁平化的风格,有时候又想要拟物化的风格.而在 Mat ...

  9. 原生JS实现Ajax及Ajax的跨域请求

      前  言          如今,从事前端方面的程序猿们,如果,不懂一些前后台的数据交互方面的知识的话,估计都不太好意思说自己是程序猿.当然,如今有着许多的框架,都有相对应的前后台数据交互的方法. ...

  10. 平衡二叉树(AVL树)

    参考资料 http://www.cnblogs.com/Cmpl/archive/2011/06/05/2073217.html http://www.cnblogs.com/yc_sunniwell ...