免费注册 查看新帖 |

Chinaunix

  平台 论坛 博客 文库
最近访问板块 发新帖
查看: 1457 | 回复: 0
打印 上一主题 下一主题

用实例说明sed的用法-2 [复制链接]

论坛徽章:
0
跳转到指定楼层
1 [收藏(0)] [报告]
发表于 2012-03-02 09:13 |只看该作者 |倒序浏览
ubuntu@ubuntu:~$ sed '/Public/R a' dat             #R(read file),执行到包含Public的行时,
1 dat                                                                    #从文件a中读入一行数据
2 Desktop
3 dir1
4 dir2
5 Documents
6 Music
7 Pictures
8 Public
@@@@@@@@ hello
9 Templates
10 Videos

命令:/b/t/T
:A,创建label A;
b A,跳转到label A处继续执行sed命令;
t A,本模式空间中,如果s///替换成功过,就跳转到label A处继续执行sed命令;没有替换成功,不执行跳转;
T A,跟t相反,本模式空间中,如果没有s///替换成功过,就跳转到label A处继续执行sed命令;替换成功,不执
行跳转;
以上三个跳转命令,如果没有跟label,且符合跳转条件时,都跳到脚本结尾;

ubuntu@ubuntu:~$ cat dat
1 dat
2 Desktop
3 dir1
4 dir2
5 Documents
6 Music
7 Pictures
8 Public
9 Templates
10 Videos

ubuntu@ubuntu:~$ sed -n '/\<[dD]/b A               #遇到包含以d或D开头的单词的行,就跳到A处把
/\<[P]/p                                                                #包含以d开头的单词的行打印出来
:A                                                                          #同时打印包含以P开头的单词的行
/\<[d]/p                                                                #
' dat                                                                      #相当于  if (包含 d/D开头的单词)
1 dat                                                                     #                    goto A
3 dir1                                                                    #            else if (P开头)
7 Pictures                                                              #                    打印
8 Public                                                                 #          :A 打印d开头的单词所在的行


ubuntu@ubuntu:~$ sed -n '/\<[dD]/b                  # 遇到包含以d或D开头的单词的行,
/\<[P]/p                                                                #跳转到脚本结尾
:A                                                                         #打印包含以P开头的单词的行
/\<[d]/p
' dat
7 Pictures
8 Public

# 命令t
ubuntu@ubuntu:~$ sed -n 's/dir/dir@@@@@@/; t A         #如果dir替换成功,
/dir/a\*****                                                                            #就跳到:A处,打印出来
:A                                                                                          #否则顺序执行下面的脚本
/\<[d]/p
' dat
1 dat
3 dir@@@@@@1
4 dir@@@@@@2
ubuntu@ubuntu:~$ sed -n 's/DIR/dir@@@@@@/; t A         #DIR没有替换成功,就不跳转,
/dir/a\*****                                                                             #顺序执行下面的脚本
:A
/\<[d]/p
' dat
1 dat
3 dir1
*****
4 dir2
*****

ubuntu@ubuntu:~$ sed -n 's/dir/dir@@@@@@/; t              #如果dir替换成功,
/dir/a\*****                                                                             #就跳到脚本结尾,不打印出来
:A
/\<[d]/p
' dat
1 dat
ubuntu@ubuntu:~$ sed -n -r 's/DIR/dir@@@@@@/; t         #DIR没有替换成功,就不跳转,
/dir/a\*****                                                                             #顺序执行下面的脚本
:A
/\<[d]/p
' dat
1 dat
3 dir1
*****
4 dir2
*****

#命令T
ubuntu@ubuntu:~$ sed -n 's/dir/dir@@@@@@/; T A          #dir替换成功,不跳转,
/dir/a\*****                                                                             #顺序执行下面的脚本
:A                                                                                           #在包含dir的行后添加*****
/\<[d]/p
' dat
1 dat
3 dir@@@@@@1
*****
4 dir@@@@@@2
*****
ubuntu@ubuntu:~$ sed -n 's/DIR/dir@@@@@@/; T A        #DIR没有替换成功,跳转到A,
/dir/a\*****                                                                            #打印出包含[以d开头的字母]的行
:A
/\<[d]/p
' dat
1 dat
3 dir1
4 dir2
ubuntu@ubuntu:~$ sed -n 's/dir/dir@@@@@@/; T             #dir替换成功,不跳转,
/dir/a\*****                                                                             #顺序执行下面的脚本
:A
/\<[d]/p
' dat
3 dir@@@@@@1
*****
4 dir@@@@@@2
*****
ubuntu@ubuntu:~$ sed -n 's/DIR/dir@@@@@@/; T            #DIR没有替换成功,
/dir/a\*****                                                                             #跳转到脚本结尾,不打印任何行
:A
/\<[d]/p
' dat

# 命令n/N, d/D
多行Next(N)命令是相对于next(n)命令的,
n(next)命令将模式空间中的内容输出,清空模式空间,然后读入下一行,然后继续执行sed脚本(并不会转移到脚本开头)
N(Next)命令则保存原来模式空间中的内容,再把新的一行读入,两者之间依靠一个换行符"\n"来分隔,然后继续执行sed脚本。

ubuntu@ubuntu:~$ cat dat
1 dat
2 Desktop
3 dir1
4 dir2
5 Documents
6 Music
7 Pictures
8 Public
9 Templates
10 Videos
ubuntu@ubuntu:~$ sed -n '/Documents/n     #遇到Documents所在的行,输出模式空间(因为使用
/M/p                                                              #了n选项,并不会输出),清空模式空间,读入下一行
' dat                                                               #读入的内容中刚好包含了”M”,就打印出来
6 Music
ubuntu@ubuntu:~$ sed -n '/Documents/N    #遇到Documents所在的行,把下一行数据添加在
/M/p                                                              #模式空间后面(两行之间自动添加\n分隔),
' dat                                                               #现在模式空间包含”M”, 打印模式空间
5 Documents                                                  #p打印整个模式空间,
6 Music                                                          #P打印模式空间第一个\n前的内容

ubuntu@ubuntu:~$ sed -n '/Documents/{     #遇到Documents所在的行,把下一行数据添加在
N                                                                   #模式空间后面(两行之间自动添加\n分隔),            
d}                                                                   #删除模式空间内容,
/Music/p
' dat
ubuntu@ubuntu:~$ sed -n '/Documents/{    #遇到Documents所在的行,把下一行数据添加在
N                                                                  #模式空间后面(两行之间自动添加\n分隔),            
D}                                                                 #删除模式空间中第一个\n前的内容,
/Music/p                                                       #打印模式空间
' dat
6 Music

前面我们说过,sed执行其实就是个大循环,每次对一行数据进行操作,一行一行的将所有的数据处理完。
对每一行操作,sed有4个步骤:
1、读入当前行数据
2、对其执行sed命令
3、输出模式空间的内容(除非-n限制了自动输出)
4、清空模式空间

# 命令h/H, g/G
h/H 将模式空间的内容copy(覆盖原有内容)/append到存储空间
g/G 将存储空间的内容copy(覆盖原有内容)/append到模式空间
H(Hold)/G(Get),都会在目的空间的原有内容之后加上一个换行符“\n”,然后才把源空间中的内容加到换行符的后面。
ubuntu@ubuntu:~$ sed -n '/dir/{h;d}             #将dir所在的行copy到(覆盖)存储空间(dir有两次)
/Doc/{g;p}' dat                                               #在Doc这一行,取出存储空间的内容,覆盖模式空间
4 dir2                                                             #打印模式空间

ubuntu@ubuntu:~$ sed -n '/dir/{h;d}             #将dir所在的行copy到(覆盖)存储空间(dir有两次)
/Doc/{G;p}' dat                                               #在Doc这一行,取出存储空间的内容,附加在模式空间
5 Documents                                                  #打印模式空间
4 dir2
ubuntu@ubuntu:~$ sed -n '/dir/{H;d}             #将dir所在的行附加到存储空间(dir有两次)
/Doc/{g;p}' dat                                                #在Doc这一行,取出存储空间的内容,覆盖模式空间
                                                                      #注意,这个空行不是我手动换的,是本命令的输出哦
3 dir1
4 dir2
ubuntu@ubuntu:~$ sed -n '/dir/{H;d}             #将dir所在的行附加到存储空间(dir有两次)
/Doc/{G;p}' dat                                               #在Doc这一行,取出存储空间的内容,附加在模式空间
5 Documents                                                  #打印模式空间
                                                                      #怎么也有个空行?
3 dir1
4 dir2


ubuntu@ubuntu:~$ cat dat                           # 命令x,交换模式空间和存储空间的内容
1 dat
2 Desktop
3 dir1
4 dir2
5 Documents
6 Music
7 Pictures
8 Public
9 Templates
10 Videos
ubuntu@ubuntu:~$ sed '/Doc/{h;d}               #遇到包含Doc的行,就把模式空间的内容
/Pic/x                                                             #放进存储空间,然后删除模式空间;
' dat                                                               #这样Doc所在的行,是不会显示出来的
1 dat                                                                                                
2 Desktop                                                       #所以第4行后直接就是第6行
3 dir1
4 dir2            
6 Music      
5 Documents                                                  #遇到包含Pic的行(第7行)后,交换模式空间和
8 Public                                                          #存储空间的内容,
9 Templates   
10 Videos

下面的例子中请注意命令p/l/P的差别
ubuntu@ubuntu:~$ sed -n '/\<D/{N;p}' dat               #遇到包含以D开头的单词的行,
2 Desktop                                                                  #就读取下一行到模式空间, 然后打印模式空间
3 dir1
5 Documents
6 Music
ubuntu@ubuntu:~$ sed -n '/\<D/{N;l}' dat                #l,以可见(visually unambiguous)的方式
2 Desktop\n3 dir1$                                                    #查看模式空间的内容,
5 Documents\n6 Music$                                            #模式空间的内容实际上是左边这个样子的

ubuntu@ubuntu:~$ sed -n '/\<D/{N}' dat               #P,打印模式空间中第一个换行符号之前的内容
2 Desktop
5 Documents

[ubuntu@bourne ~]$ cat dat1
hello Tom, hello Michel, hello Sara
hello Bourne, hello Ellen, hello Marco

[ubuntu@bourne ~]$ sed 's/hello/hi/' dat1                #将每个模式空间(行)中第一个hello替换为hi
hi Tom, hello Michel, hello Sara
hi Bourne, hello Ellen, hello Marco
[ubuntu@bourne ~]$ sed 's/hello/hi/g' dat1              #g(global),
hi Tom, hi Michel, hi Sara                                           #将每个模式空间(行)中所有的hello替换为hi
hi Bourne, hi Ellen, hi Marco
[ubuntu@bourne ~]$ sed 's#hello#hi#g' dat1            #s#...#...#g 可以用别的分割符号
hi Tom, hi Michel, hi Sara
hi Bourne, hi Ellen, hi Marco
[ubuntu@bourne ~]$ sed 's hello hi g' dat1               #s ... ... g
hi Tom, hi Michel, hi Sara
hi Bourne, hi Ellen, hi Marco
[ubuntu@bourne ~]$ sed 's-hello-hi-g' dat1              #s-...-...-g
hi Tom, hi Michel, hi Sara
hi Bourne, hi Ellen, hi Marco
[ubuntu@bourne ~]$ sed 's)hello)hi)g' dat1               #s)...)...)g
hi Tom, hi Michel, hi Sara
hi Bourne, hi Ellen, hi Marco

ubuntu@ubuntu:~$ sed -n -r '/Pub/{N         #将模式空间的内容写入文件b
w b                                                              #遇到包含Pub的行时,将下一行的内容添加到模式空间
}' dat                                                            #模式空间的内容为:8 Public\n9 Templates
ubuntu@ubuntu:~$ cat b
8 Public
9 Templates
ubuntu@ubuntu:~$ sed -n -r '/Pub/{N         #将模式空间中第一个换行符号之前的内容写入文件b
W b
}' dat
ubuntu@ubuntu:~$ cat b
8 Public

#大小写转换的经典用法
ubuntu@ubuntu:~$ sed 'y/abcdefghijklmnopqrstuvwxyz/ABCDEFGHIJKLMNOPQRSTUVWXYZ/' dat
1 DAT                                                                 #y,直译,将[a-z]依次替换为[A-Z],
2 DESKTOP                                                         #本例将小写字母全部转换为大写字母
3 DIR1
4 DIR2
5 DOCUMENTS
6 MUSIC
7 PICTURES
8 PUBLIC
9 TEMPLATES
10 VIDEOS
ubuntu@ubuntu:~$ sed 'y/abcdefghijklmnopqrstuvwxyz/qazxswedcvfrtgbnhyujmkiolp/' dat
1 xqj                                                                    #将[a-z]依次替换为[qazxsw...olp]
2 Dsufjbn                                                             #这样就成了一个简单的加密器
3 xcy1                                                                  #y/明文串/密文串/
4 xcy2                                                                  #注意,明文串和密文串中都不能出现相同的字母、
5 Dbzmtsgju                                                        #数字、符号,前后两个串的长度要相等
6 Mmucz
7 Pczjmysu
8 Pmarcz
9 Tstnrqjsu
10 Vcxsbu
ubuntu@ubuntu:~$ sed 'y/abcdefghijklmnopqrstuvwxyz/qazxswedcvfrtgbnhyujmkiolp/' dat > tmp
ubuntu@ubuntu:~$ sed 'y/qazxswedcvfrtgbnhyujmkiolp/abcdefjhijklmnopqrstuvwxyz/' tmp
1 dat                                                                    #将明文串和密文串交换位置,就成了解码器
2 Desktop                                                            #y/密文串/明文串/
3 dir1
4 dir2
5 Documents            
6 Music
7 Pictures
8 Public
9 Templates
10 Videos

ubuntu@ubuntu:~$ sed -n '/\w{3}[12]{1}/p' dat
ubuntu@ubuntu:~$ sed -n -r '/\w{3}[12]{1}/p' dat             # r,使用扩展正则表达式时,要加-r选项
3 dir1
4 dir2

您需要登录后才可以回帖 登录 | 注册

本版积分规则 发表回复

  

北京盛拓优讯信息技术有限公司. 版权所有 京ICP备16024965号-6 北京市公安局海淀分局网监中心备案编号:11010802020122 niuxiaotong@pcpop.com 17352615567
未成年举报专区
中国互联网协会会员  联系我们:huangweiwei@itpub.net
感谢所有关心和支持过ChinaUnix的朋友们 转载本站内容请注明原作者名及出处

清除 Cookies - ChinaUnix - Archiver - WAP - TOP