用户名: 密码: 忘记密码? 注册

sed shell编程

作者:  时间: 2010-09-28

sed是一个非交互性文本流编辑器,是一种重要的文本过滤工具。
调用(三种方式)
1.使用sed命令行
sed [选项] sed命令 输入文件
2.使用sed脚本文件
sed [选项] -f sed脚本文件 输入文件
3.将sed命令插入脚本文件,并使sed脚本可执行。
sed浏览输入文件时,缺省从第一行开始,有两种方式定位文本
1)使用行号(可以是数字,和是行号范围)
2)使用正规表达式
基本sed编辑命令
p 打印匹配行
= 显示文件行
a\ 在指定行号后附加新的文本信息
i\ 在指定行号后插入新的文本信息
d 删除指定行
c\ 用新的文本替换定位文本
s 使用替换模式替换相应的模式
r 从另一个文件种读文本
w 把文本写到一个文件
q 第一个匹配行完成后退出或立即退出
l 显示八进制ASCII代码等价的控制字符
{} 在定位执行的命令组
n 从另一个文件种读文本下一行,并附加在下一行
g 将模式粘贴到/pattern n/
y 传送字符

shell>>sed -n '2p' /etc/passwd  打印出来/etc/passwd这个文件中第二行的内容出来
sed -n '1,3p' /etc/passwd       打印出来 1 - 3行内容了

使用模式和行号进行查询
sed -n '/dev/'p /etc/fstab         ‘能够得到相匹配的行记录出来的
sed -n '6,/dev/'p /etc/fstab

匹配元素字符
sed -n '/\#/'p /etc/fstab

显示整个文件
只需将行的范围设为第一行到最后一行 (1,$)
sed -n '1.$p' /etc/fstab

首行 '1p'

最后一行'$p"

任意字符
sed -n '/.*ing/'p /etc/passwd

打印行号(=)
sed -e '/reiserfs/=' /etc/fstab
sed -e = /etc/fstab
sed -n '/reiserfs/=' /etc/fstab
sed -n = /etc/fstab
如果只打印行号以及匹配行,必须使用两个sed命令,并使用-e选项
sed -n -e '/reiserfs/p' -e '/reiserfs/=' /etc/fstab


替换文本
格式:
[address [,address]] s /pattern-tofind/replacement-pattern/ [g p w n]
替换选项
g 全局替换
n 将所有替换值写入标准输出(缺省)
p 是-n无效
w 使输出定向到一个文件

sed 's/reiserfs/REISERFS/' /etc/fstab
sed 's/\///g' /etc/fstab #删除/号

在符合条件的行前面添加一个#字符,起到注释的作用。
sed -i '/^adm/ s/^/#/g' /tmp/list.h
{评注:2009-03-24}
有一个文本文件text.txt内容如下:
#从服务器的配置:复制主服务器,帐号,密码,库,表
master-host = 192.168.100.90
master-user =repuser
master-password =123456
Replicate_Do_DB = mytianya
replicate-do-db=tianya_test
replicate-wild-do-table = mytianya.tb_user_space
我现在需要将master开头的那三行 前面添加上注释的话那我可以这样来写SED命令的
sed -i '/^master/ s/^/#/g' test.txt
好爽呀!哈哈
我想这个应该是这样来理解的呀!
第一步:找到以master打头的这一行然后 实现后面的s/^/#/g的哦!
而且能够直接写到文本里面去的呀!这样的话那我再测试一下原来的那个SED命令吧!

{现在来解决之前这个问题吧!}
之前 的IP正则匹配的方法是什么来着?
sed -n -e '/[0-9]\{1,3\}\.[0-9]\{1,3\}\.[0-9]\{1,3\}\.[0-9
]\{1,3\}/p' test
以下是我的文本文件内容:
ns1     IN      A     218.77.130.173
m.portal.bbs    IN      A       19.2.168.100
m.user.bbs      IN      A       19.2.168.27
这样就能够将其中的IP值给替换出来的呀!
终于写出来了一个SED正则表达式了好高兴呀!整整困扰了我N天了哈哈!

sed -i  '/^ns1/ s/[0-9]\{1,3\}\.[0-9]\{1,3\}\.[0-9]\{1,3\}
\.[0-9]\{1,3\}/123/g' test

我终于明白了:如果要进行两步操作的话就可以直接这样分开两步进行操作的处理!

{OK}现在来将要写的SED命令都写好吧!
S1:的SED命令如下:
sed -i '/^master/ s/^/#/g' my.cnf  {S1的命令就是这样写的哈哈!}
S2:的SED命令如下:
sed -i  '/^master-host/ s/[0-9]\{1,3\}\.[0-9]\{1,3\}\.[0-9
]\{1,3\}\.[0-9]\{1,3\}/123/g' test
分析命令:首先第一步找到想要找的这一行然后将其替换掉就行了!
非常地方便的呀!
S3:的SED命令
之前的命令:
找到对应的域名然后将其中的IP值替换掉就行了!
sed -i  '/^ns1/ s/[0-9]\{1,3\}\.[0-9]\{1,3\}\.[0-9]\{1,3\}
\.[0-9]\{1,3\}/123/g' test

sed -i '/\<m.user.bbs/ s/[0-9]\{1,3\}\.[0-9]\{1,3\}\.[0-9]
\{1,3\}\.[0-9]\{1,3\}/19.2.168.110/g' test

现在我们这样来做:将其封装到一个Python脚本中去传入参数:
之后的命令:
将  2009030309 ; Serial  中的数字添加1 之后再保存起来!
?这个还依旧是一个问题。如何进行相关的逻辑运算起来呢?
这还存在一个运算的关系了!

开始封装成脚本直接调用:
S1端的脚本类如下:
cmd = """sed -i '/^master/ s/^/#/g' /etc/my.cnf """
log.log("modify my.cnf command:"+cmd)
if os.system(cmd)==0:
  log.log("modify my.cnf is ok!")
else:
  log.log("modify my.cnf not ok!")

S1端只须将包含了Master的替换掉就可以了的!
S2端的脚本封装类如下:
def S2Shell(self,newIP):
        cmd = """sed -i '/^master-host/ s/[0-9]\{1,3\}\.[0-9]\{1,3\}\.[0-9]\{1,3\}\.[0-9]\{1,3\}/"""+newIP+"""/g' /etc/my.cnf"""
        return os.system(cmd)
封装到了一个类中然后就直接调用就可以了的!非常地方便的哦!
S3端的脚本进行封装处理:
之前的代码进行封装:
class PShell:
    #Get Two Parameters:domain and nip
    def Shell(self,domain,nip):
        cmd = """sed -i '/\<"""+domain+"""/ s/[0-9]\{1,3\}\.[0-9]\{1,3\}\.[0-9]\{1,3\}\.[0-9]\{1,3\}/"""+nip+"""/g' /var/named/hk.hn"""
        print cmd
        return  os.system(cmd)
将搜索到的域名与新的IP值加进来做搜索操作用的!
调用的方法如下:
if obj.Shell("m.my.bbs", "127.0.0.1")==0:
        print "ok"
    else:
        print "down"

之后的脚本的代码如下:

如何用SED来尝试一下试试看吧!

{插入一下:
5. 元字符集

^ 锚定行的开始 如:/^sed/匹配所有以sed开头的行。 

$ 锚定行的结束 如:/sed$/匹配所有以sed结尾的行。 

. 匹配一个非换行符的字符 如:/s.d/匹配s后接一个任意字符,然后是d。 

* 匹配零或多个字符 如:/*sed/匹配所有模板是一个或多个空格后紧跟sed的行。 

[] 匹配一个指定范围内的字符,如/[Ss]ed/匹配sed和Sed。 

[^] 匹配一个不在指定范围内的字符,如:/[^A-RT-Z]ed/匹配不包含A-R和T-Z的一个字母开头,紧跟ed的行。 

\(..\) 保存匹配的字符,如s/\(love\)able/\1rs,loveable被替换成lovers。 

& 保存搜索字符用来替换其他字符,如s/love/**&**/,love这成**love**。 

\< 锚定单词的开始,如:/\<love/匹配包含以love开头的单词的行。 

\> 锚定单词的结束,如/love\>/匹配包含以love结尾的单词的行。 

x\{m\}重复字符x,m次,如:/0\{5\}/匹配包含5个o的行。 

x\{m,\} 重复字符x,至少m次,如:/o\{5,\}/匹配至少有5个o的行。 

x\{m,n\}重复字符x,至少m次,不多于n次,如:/o\{5,10\}/匹配5--10个o的行。





sed 's/m.my.bbs/MyBBS/' hk.ty  --可以实现将hk.ty这个文件中的m.my.bbs替换成MyBBS这个值的了!

搜索到对应的域名之后再将里面的IP值替换过来就OK了!

将sed结果写入文件 (w)
sed '1,2 w filename' /etc/fstab

快速一行命令 ([]表示空格)
  's/\.$//g' 删除以句点结尾的行
  '-e/abcd/d' 删除包含abcd的行     可以将包含了这些字符串的这一行给删除掉
  's/[][][]*/[]/ 用一个空格代替三个以上空格
  '/^$/d' 删除空行
  's/^.//g' 删除第一个字符
  's/col\(...\)//g' 删除col和后面紧跟的3个字符
  's/[]/[] //g' 删除所用空格并用tab键替代
  's/^[]//g' 删除行首所有tab键
  's/[]*//g' 删除所有tab键

:可以这样来实现的:第一步将含有需要删除的域名这一行记录删除掉
第二步:将新的行记录插入进来!