知识屋:更实用的电脑技术知识网站
所在位置:首页 > 操作系统 > linux

Linux.Shell编程笔记-流编辑Sed

发布时间:2014-09-05 13:28:27作者:知识屋

第七章 流编辑

什么是sed

挑选编辑器

UNIX/Linux世界叶,有许多的文本编辑器可供选择。例如,最常使用的VI和emacs。在有了自己最熟悉的编辑利器后,才能轻松处理UNIX下各种管理和编辑任务。

像VI,emacs这类编辑器,被称为交互式编辑器。交互式编辑器虽然很棒,但是当我们需要在程序中完成文本处理工作时,它就帮不上忙了。此时就需要一些能够在命令行完成的编辑工具。

我们期待一切管理流程都能自动化,包括能够以批处理的方式编辑文件。许多文本编辑的需求都是对文本的每一行进行相同的操作。这样的处理就能够用sed来完成。

sed号称流编辑器。什么是流编辑器呢?流编辑器可以对从管道这样的标准输入接收的数据进行编辑。因此,无需将要编辑的数据存储在磁盘上的文件中。因为可以轻易将数据管道输出到sed,所以,将sed用作强大的shell脚本中长而复杂的管道很容易。

Sed的版本

查看版本方式

[houchangren@ebsdi-23260-oozie ~]$ sed--versionGNU sed version 4.1.5Copyright (C) 2003 Free SoftwareFoundation, Inc.This is free software; see the source forcopying conditions.  There is NOwarranty; not even for MERCHANTABILITY orFITNESS FOR A PARTICULAR PURPOSE,to the extent permitted by law.

Sed实例

Sed的工作方式

sed通过对输入数据执行任意数量用户指定的编辑操作(命令)。sed是基于行的,因此

按顺序对每一行执行命令。然后,sed将其结果写入标准输出(stdout ),它不修改任何输入

文件。

参数列表参考:

http://www.cnblogs.com/edwardlost/archive/2010/09/17/1829145.html

示例:

[houchangren@ebsdi-23260-oozie shell]$ head-n5 /etc/passwd > /tmp/passwd.bak[houchangren@ebsdi-23260-oozie shell]$cat  /tmp/passwd.bakroot:x:0:0:root:/root:/bin/bashbin:x:1:1:bin:/bin:/sbin/nologindaemon:x:2:2:daemon:/sbin:/sbin/nologinadm:x:3:4:adm:/var/adm:/sbin/nologinlp:x:4:7:lp:/var/spool/lpd:/sbin/nologin[houchangren@ebsdi-23260-oozie shell]$ sed-e 'd'  /tmp/passwd.bak[houchangren@ebsdi-23260-oozie shell]$ sed-e '1d' /tmp/passwd.bakbin:x:1:1:bin:/bin:/sbin/nologindaemon:x:2:2:daemon:/sbin:/sbin/nologinadm:x:3:4:adm:/var/adm:/sbin/nologinlp:x:4:7:lp:/var/spool/lpd:/sbin/nologin[houchangren@ebsdi-23260-oozie shell]$ sed-e '3d' /tmp/passwd.bakroot:x:0:0:root:/root:/bin/bashbin:x:1:1:bin:/bin:/sbin/nologinadm:x:3:4:adm:/var/adm:/sbin/nologinlp:x:4:7:lp:/var/spool/lpd:/sbin/nologin

上方的‘d’就是参数应用就是默认的就是删除每行,指定数字就删除第几行的记录,第一次删除了第一行1行显示后四条。第二次删除第3条,显示剩余其他4条。

NOTE

在该例中,还有几件事要注意:

1)根本没有修改/tmp/passwd.bak这还是因为sed只读取在命令行指定的文件,将其用作输入-它不试图修改该文件。

2)要注意的事是sed是面向行的。’d’命令不是简单地告诉sed一下子删除所有输入数据。相反,sed逐行将/etc/passwd.bak的每一行读入其称为模式缓冲区的内部缓冲区一旦将一行读入模式缓冲区,它就执行’d’命令,然后打印模式缓冲区的内容(在本例中没有内容).如果不使用地址,命令将应用到所有行。

3)括起‘d’命令的单引号的用法。养成使用单引号来括起scd命令的习惯是个好主意,这样可以禁用shell扩展。

Sed工作的地址范围

指定命令的操作行区域,比如下边1-2行和3-6行,当然没有第6行,就只有多少删除多少了。

[houchangren@ebsdi-23260-oozie shell]$ sed-e '1,2d' /tmp/passwd.bak
daemon:x:2:2:daemon:/sbin:/sbin/nologin
adm:x:3:4:adm:/var/adm:/sbin/nologin
lp:x:4:7:lp:/var/spool/lpd:/sbin/nologin
[houchangren@ebsdi-23260-oozie shell]$ sed-e '3,6d' /tmp/passwd.bak
root:x:0:0:root:/root:/bin/bash
bin:x:1:1:bin:/bin:/sbin/nologin

sed忽略注释

[houchangren@ebsdi-23260-oozie shell]$ cat/etc/rc.local#!/bin/sh## This script will be executed *after* allthe other init scripts.# You can put your own initialization stuffin here if you don't# want to do the full Sys V style initstuff. touch /var/lock/subsys/localhive --service hiveserver &[houchangren@ebsdi-23260-oozie shell]$ sed-e '/^#/d' /etc/rc.local | more touch /var/lock/subsys/localhive --service hiveserver & [houchangren@ebsdi-23260-oozie shell]$ sed-e '/^[^#]/d' /etc/rc.local | more#!/bin/sh## This script will be executed *after* allthe other init scripts.# You can put your own initialization stuffin here if you don't# want to do the full Sys V style initstuff.
规则表达式

Sed中使用的规则表达式字符

 

字符

描述

^

与行首匹配

$

与行尾匹配

.

与任意一个字符匹配

*

与前一个字符的零个或多个出现匹配

[]

与[]之内的所有字符匹配

 

Sed规则表达式实例

 

规则表达式

描述

/./

将与包含至少一个字符的任何行匹配

/../

将与包含至少两个字符的任何行匹配

/^#/

将与以‘#’开头的任意行匹配,通常这是注释

/}$/

将与‘}’结束的任意行匹配

/} *$/

注意在}后面有一个空格,这将与‘}’后而跟随零个或多个空格结束的任意行匹配配

/[abc]/

将与包含小写字母‘a,b,c的任意行匹配

/^[abc]/

将与以a,b,c任何开始的任何行匹配

 

-n参数 这个选项告诉sed 除非明确要求打印模式空间,否则不这样做。

[houchangren@ebsdi-23260-oozie shell]$ sed-n -e '/^[echo]/p' user_login.shecho " user $1 is on"elseecho " user $1 is off" [houchangren@ebsdi-23260-oozie shell]$ sed-n -e '/[abc]/p' user_login.sh#!/bin/bashfunction user_login(){echo " user $1 is on"echo " user $1 is off" [houchangren@ebsdi-23260-oozie shell]$ cata.c#include <stdio.h>#include <math.H> int main (){// int base,n;// scanf("%d,%d/n",&b,&n) }[houchangren@ebsdi-23260-oozie shell]$ sed-n -e '/main[[:space:]]*(/,/^ }/p' a.c | moreint main (){// int base,n;// scanf("%d,%d/n",&b,&n) }[houchangren@ebsdi-23260-oozie shell]$ sed-n -e '/^///p' a.c | more// int base,n;// scanf("%d,%d/n",&b,&n) 

强大的Sed功能

替换

替换公式: sed -e s[符号][要替换的字符][符号][替换后的字符][符号][g]

实例:

[houchangren@ebsdi-23260-oozie data]$ cattwister.txt    //查看一信息I wish to wish the wish you wish to wish,but if you wish the wish the witch wishes, I won't wish the wish you wish towish.I wish to wish the wish you wish to wish,but if you wish the wish the witch wishes, I won't wish the wish you wish towish.I wish to wish the wish you wish to wish,but if you wish the wish the witch wishes, I won't wish the wish you wish towish.I wish to wish the wish you wish to wish,but if you wish the wish the witch wishes, I won't wish the wish you wish towish. [houchangren@ebsdi-23260-oozie data]$ sed-e 's/wish/want/' twister.txt   //替换每一行的第一个匹配I want to wish the wish you wish to wish,but if you wish the wish the witch wantes, I won't wish the wish you wish towish.I want to wish the wish you wish to wish,but if you wish the wish the witch wantes, I won't wish the wish you wish towish.I want to wish the wish you wish to wish,but if you wish the wish the witch wantes, I won't wish the wish you wish towish.I want to wish the wish you wish to wish,but if you wish the wish the witch wantes, I won't wish the wish you wish towish. [houchangren@ebsdi-23260-oozie data]$ sed-e 's/wish/want/g' twister.txt  //替换匹配到的所有的I want to want the want you want to want,but if you want the want the witch wantes, I won't want the want you want towant.I want to want the want you want to want,but if you want the want the witch wantes, I won't want the want you want towant.I want to want the want you want to want,but if you want the want the witch wantes, I won't want the want you want towant.I want to want the want you want to want,but if you want the want the witch wantes, I won't want the want you want towant. [houchangren@ebsdi-23260-oozie data]$ sed-e '1,2s/wish/want/' twister.txt  //替换1到2行的第一个匹配I want to wish the wish you wish to wish,but if you wish the wish the witch wantes, I won't wish the wish you wish towish.I wish to wish the wish you wish to wish,but if you wish the wish the witch wishes, I won't wish the wish you wish towish.I wish to wish the wish you wish to wish,but if you wish the wish the witch wishes, I won't wish the wish you wish towish.I wish to wish the wish you wish to wish,but if you wish the wish the witch wishes, I won't wish the wish you wish towish. [houchangren@ebsdi-23260-oozie data]$ sed-e '1,2s/wish/want/g' twister.txt  //替换1到2行的所有匹配I want to want the want you want to want,but if you want the want the witch wantes, I won't want the want you want towant.I wish to wish the wish you wish to wish,but if you wish the wish the witch wishes, I won't wish the wish you wish towish.I wish to wish the wish you wish to wish,but if you wish the wish the witch wishes, I won't wish the wish you wish towish.I wish to wish the wish you wish to wish,but if you wish the wish the witch wishes, I won't wish the wish you wish towish. [houchangren@ebsdi-23260-oozie data]$

因为有的时候需要操作’/’符号,那么再用‘/’线

来做符号就不方便了,可以改成其他的,比如冒号‘:’

[houchangren@ebsdi-23260-oozie data]$ cathivepath.txt/usr/local/hive-0.7.1-cdh3u6/bin/hive/usr/local/hive-0.7.1-cdh3u6/bin/hive/usr/local/hive-0.7.1-cdh3u6/bin/hive/usr/local/hive-0.7.1-cdh3u6/bin/hive[houchangren@ebsdi-23260-oozie data]$ sed-e s:/usr/local:/usr/lib:g hivepath.txt/usr/lib/hive-0.7.1-cdh3u6/bin/hive/usr/lib/hive-0.7.1-cdh3u6/bin/hive/usr/lib/hive-0.7.1-cdh3u6/bin/hive/usr/lib/hive-0.7.1-cdh3u6/bin/hive

过滤所有的html标签实例

[houchangren@ebsdi-23260-oozie data]$ cattest.html<!DOCTYPE HTML PUBLIC "-//W3C//DTDHTML 4.0 Transitional//EN"><HTML> <HEAD> <TITLE> New Document </TITLE> <META NAME="Generator" CONTENT="EditPlus"> <META NAME="Author" CONTENT=""> <META NAME="Keywords" CONTENT=""> <META NAME="Description" CONTENT=""> </HEAD>  <BODY>  I'mtest html </BODY></HTML> [houchangren@ebsdi-23260-oozie data]$ sed-e 's/<[^>]*>//g' test.html New DocumentI'mtest html

组合命令

组合多条命令

在同时使用多个命令的时候可以使用分号“;”

[houchangren@ebsdi-23260-oozie data]$ sed-e '=' fruit.txt  // 等号=是显示行号1%%banae 2banana  3apple4Presimmon5%%banae 6apple 7Banana  8orange  9presimmon[houchangren@ebsdi-23260-oozie data]$ sed-e '=;p' fruit.txt //显示行号和打印默认会打印所以两次1%%banae %%banae 2banana  banana  3appleapple4PresimmonPresimmon5%%banae %%banae 6apple apple 7Banana  Banana  8orange  orange  9presimmonpresimmon[houchangren@ebsdi-23260-oozie data]$ sed-n -e '=;p' fruit.txt //指定-n后打印p参数的命令1%%banae 2banana  3apple4Presimmon5%%banae 6apple 7Banana  8orange  9Persimmon[houchangren@ebsdi-23260-oozie data]$ sed-n -e 'p' -e = fruit.txt  //-e可以指定多个命令%%banae 1banana  2apple3Presimmon4%%banae 5apple 6Banana  7orange  8presimmon9 

有时候当太多的命令需要连接一起执行的时候-e可能也不够使用了,可以使用-f指定文本,然后在文本中编写命令

[houchangren@ebsdi-23260-oozie data]$ cathivepath.txt/usr/local/hive-0.7.1-cdh3u6/bin/hive/usr/local/hive-0.7.1-cdh3u6/bin/hive/usr/local/hive-0.7.1-cdh3u6/bin/hive/usr/local/hive-0.7.1-cdh3u6/bin/hive//1d是删除一行,接着是/usr/local替换成/usr/bin,接着打印,接着显示行号[houchangren@ebsdi-23260-oozie data]$ cat../sed/test.sed   1ds:/usr/local/:/usr/lib/:gp=[houchangren@ebsdi-23260-oozie data]$ sed-n -f ../sed/test.sed  hivepath.txt/usr/lib/hive-0.7.1-cdh3u6/bin/hive2/usr/lib/hive-0.7.1-cdh3u6/bin/hive3/usr/lib/hive-0.7.1-cdh3u6/bin/hive4
将多条命令应用到一个地址范围

在指定了一个地址范围比如 1-5行,然后执行多个操作

[houchangren@ebsdi-23260-oozie data]$ head-n10 /etc/passwd > pwd.piece[houchangren@ebsdi-23260-oozie data]$ catpwd.pieceroot:x:0:0:root:/root:/bin/bashbin:x:1:1:bin:/bin:/sbin/nologindaemon:x:2:2:daemon:/sbin:/sbin/nologinadm:x:3:4:adm:/var/adm:/sbin/nologinlp:x:4:7:lp:/var/spool/lpd:/sbin/nologinsync:x:5:0:sync:/sbin:/bin/syncshutdown:x:6:0:shutdown:/sbin:/sbin/shutdownhalt:x:7:0:halt:/sbin:/sbin/haltmail:x:8:12:mail:/var/spool/mail:/sbin/nologinnews:x:9:13:news:/etc/news:[houchangren@ebsdi-23260-oozie data]$ sed -n -e'1,5{s:/bin/bash:/bin/sh:g;s/:/|/g;p}' pwd.piece[houchangren@ebsdi-23260-oozie data]$ sed-n -e '1,5{s:/bin/bash:/bin/sh:g;s/:/|/g;p}' pwd.pieceroot|x|0|0|root|/root|/bin/shbin|x|1|1|bin|/bin|/sbin/nologindaemon|x|2|2|daemon|/sbin|/sbin/nologinadm|x|3|4|adm|/var/adm|/sbin/nologinlp|x|4|7|lp|/var/spool/lpd|/sbin/nologin[houchangren@ebsdi-23260-oozie data]$ [houchangren@ebsdi-23260-oozie data]$ cat../sed/pwd.sed1,5{s:/bin/bash:/bin/sh:gs/:/|/gp}[houchangren@ebsdi-23260-oozie data]$ sed-n -f ../sed/pwd.sed pwd.pieceroot|x|0|0|root|/root|/bin/shbin|x|1|1|bin|/bin|/sbin/nologindaemon|x|2|2|daemon|/sbin|/sbin/nologinadm|x|3|4|adm|/var/adm|/sbin/nologinlp|x|4|7|lp|/var/spool/lpd|/sbin/nologin
实例的例子

LINUX和DOS/Windows系统纯文本格式的换行方式是不同的。这个脚本将UNIX风格的文本转换成DOS/windows格式。你可能知道,基于DOS、windows的文本文件在每一行末尾有一个CR(回车)和LF(换行),而UNIX文本只有一个换行。有时可能需要将某unix文本移至

Windows系统,该脚本将为你执行必需的格式转换.

>>> sed  -e  ‘s/$//r/’myunix.txt > mydos.txt

在该脚本中,‘$’规则表达式将与行的末尾匹配,而`/r'告诉sed在其之前插入个回车。

在换行之前插入回车,每一行立即就以CR/LF结束。

反之,有好多的时候下载的网络文件是dos/windows文件,在unix操作确实有问题,比如bash。用sed调用将把dos/windows格式的文本转换成可信赖的unix格式

>>> sed –e ‘s/.$//’ mydos.txt >myunix.txt

该脚本的工作原理很简单:替代规则表达式与一行的的最末字符匹配,而该字符恰好就是回车。我们用空字符替换它,从而将其从输出中彻底删除。如果使用改脚本,并注意到己经删除了输出中每行的最末字符,那么,你就指定了已经是UNIX式的文本文件。

Sed实践

要求:

1. 把“小明“的名字改成“李小明”;

2. 删除头三行

3. 显示5-10行

4. 删除包含“排除“的行

5. 显示所有生日在Nov和Dec之间的行

6. 所有姓张开头的行,前边标记 ***

7. 用“试用期人员“替换包含”试用“的行

8. 把刘发明的生日 1986/11/11

9. 删除所有的空白行

10. 写一个脚本,将第一行插入Personnel File ,删除所有以500结尾的工资,显示文件内容,把电话号码和生日颠倒一下,在文件的结尾添加the end。

11.把包含“试用”的行中姓名提取出来,然后正行替换成“试用人员:”+name

数据内容:

[houchangren@ebsdi-23260-oozie data]$ cat persons.txt小明:010-68239343:我是经理:1988/01/10:5000黎明:010-68239343:我是经理:1988/08/10:5000张学友:010-68239343:我是经理:1988/04/10:5000 周云飞:010-68239343:业务排除了。:1988/10/10:500丽泽卡:010-68239343:没有描述:1988/12/10:2000刘发明:010-68239343:没有描述:1988/11/10:5340 大荒西:010-68239343:没有描述:1988/10/10:1000斯蒂芬:010-68239343:没有描述:1988/10/10:1000甄格大:010-68239343:试用期中.:1988/10/10:200 任务操作:1.[houchangren@ebsdi-23260-oozie data]$ sed-n -e 's:小明:李小明:gp' persons.txt李小明:010-68239343:我是经理:1988/01/10:50002.[houchangren@ebsdi-23260-oozie data]$ sed -e '1,3d' persons.txt 周云飞:010-68239343:业务排除了。:1988/10/10:500丽泽卡:010-68239343:没有描述:1988/12/10:2000刘发明:010-68239343:没有描述:1988/11/10:5340 大荒西:010-68239343:没有描述:1988/10/10:1000斯蒂芬:010-68239343:没有描述:1988/10/10:1000甄格大:010-68239343:试用期中.:1988/10/10:2003.周云飞:010-68239343:业务排除了。:1988/10/10:500丽泽卡:010-68239343:没有描述:1988/12/10:2000刘发明:010-68239343:没有描述:1988/11/10:5340 4.[houchangren@ebsdi-23260-oozie data]$ sed -e '/排除/d' persons.txt小明:010-68239343:我是经理:1988/01/10:5000黎明:010-68239343:我是经理:1988/08/10:5000张学友:010-68239343:我是经理:1988/04/10:5000 丽泽卡:010-68239343:没有描述:1988/12/10:2000刘发明:010-68239343:没有描述:1988/11/10:5340 大荒西:010-68239343:没有描述:1988/10/10:1000斯蒂芬:010-68239343:没有描述:1988/10/10:1000甄格大:010-68239343:试用期中.:1988/10/10:200 5.[houchangren@ebsdi-23260-oozie data]$ sed -n '/[:::][0-9]*[:/:]1[1-2]/p' persons.txt丽泽卡:010-68239343:没有描述:1988/12/10:2000刘发明:010-68239343:没有描述:1988/11/10:53406.[houchangren@ebsdi-23260-oozie data]$ sed -n 's/^张/***张/p' persons.txt***张学友:010-68239343:我是经理:1988/04/10:5000 7.[houchangren@ebsdi-23260-oozie data]$ sed -e 's/^.*试用.*$/试用期人员/g' persons.txt小明:010-68239343:我是经理:1988/01/10:5000黎明:010-68239343:我是经理:1988/08/10:5000张学友:010-68239343:我是经理:1988/04/10:5000 周云飞:010-68239343:业务排除了。:1988/10/10:500丽泽卡:010-68239343:没有描述:1988/12/10:2000刘发明:010-68239343:没有描述:1988/11/10:5340 大荒西:010-68239343:没有描述:1988/10/10:1000斯蒂芬:010-68239343:没有描述:1988/10/10:1000试用期人员 8.[houchangren@ebsdi-23260-oozie data]$ sed -n -e '/刘发明/s/:[0-9]*//.*//.*:/:1986//11//11:/gp' persons.txt刘发明:010-68239343:没有描述:1986/11/11:53409.[houchangren@ebsdi-23260-oozie data]$ sed -e '/^$/d' persons.txt小明:010-68239343:我是经理:1988/01/10:5000黎明:010-68239343:我是经理:1988/08/10:5000张学友:010-68239343:我是经理:1988/04/10:5000周云飞:010-68239343:业务排除了。:1988/10/10:500丽泽卡:010-68239343:没有描述:1988/12/10:2000刘发明:010-68239343:没有描述:1988/11/10:5340大荒西:010-68239343:没有描述:1988/10/10:1000斯蒂芬:010-68239343:没有描述:1988/10/10:1000甄格大:010-68239343:试用期中.:1988/10/10:200 10. [houchangren@ebsdi-23260-oozie data]$ cat ../sed/person.sed/500$/ds//(.*/)/(:.*:/)/(.*/)/(:.*:/)/(.*/)//1/4/3/2/5/g1i personnel file$a the end [houchangren@ebsdi-23260-oozie data]$sed  -f ../sed/person.sed persons.txtpersonnel file小明:1988/01/10:我是经理:010-68239343:5000黎明:1988/08/10:我是经理:010-68239343:5000张学友:1988/04/10:我是经理:010-68239343:5000 丽泽卡:1988/12/10:没有描述:010-68239343:2000刘发明:1988/11/10:没有描述:010-68239343:5340 大荒西:1988/10/10:没有描述:010-68239343:1000斯蒂芬:1988/10/10:没有描述:010-68239343:1000甄格大:1988/10/10:试用期中.:010-68239343:200 the end 11.[houchangren@ebsdi-23260-oozie data]$ sed -n -e '/试用/s//(.*/):.*:.*:.*:.*/试用期人员:/1/gp' persons.txt | more试用期人员:甄格大
(免责声明:文章内容如涉及作品内容、版权和其它问题,请及时与我们联系,我们将在第一时间删除内容,文章内容仅供参考)
收藏
  • 人气文章
  • 最新文章
  • 下载排行榜
  • 热门排行榜