think tips
D:在模式空间中 删除开头到第一个回车符间的所有字符,并且 从模式空间的开头 开始下一个cyle(从头到尾的命令行匹配),不打印。
d:删除特定行
n:读入下一行到(替换)pattern space,并且将下一个命令应用于它
N:将下一行读入pattern space,并且附在之前的内容后
G:将holder space的内容附在pattern space内容后, 结果就是加了个回车
g:将holder space的内容替换pattern space
p:打印当前pattern space
P:打印当前pattern space的第一行
t label
if分支,从最后一行开始,条件一旦满足或者T,t命令,将导致分支到带有标号的命令处,或者到脚本的末尾。
T label
错误分支,从最后一行开始,一旦发生错误或者T,t命令,将导致分支到带有标号的命令处,或者到脚本的末尾
=写出行号
vi
里面用%表示全局替换
也支持正则表达式
近来看到几个不是很常见,但是比较有用的sed例子,都和hold space与pattern space有关,于是对几个例子做了自己认为正确的解释,贴出来与大家共享并请指正,继续讨论
例子一
sed G
在文件每一行下面输出一个空行
代码:
$ cat foo
11111111111111
22222222222222
33333333333333
44444444444444
55555555555555
$ sed G foo
11111111111111
22222222222222
33333333333333
44444444444444
55555555555555
解释:
sed 中 G 的用法
The G function appends the contents of the holding area to the contents of the pattern space. The former and new contents are separated by a newline. The maximum number of addresses is two.
hold space : 保持空间(或者叫保留空间、缓冲区),初始为空
pattern space :模式空间
在上面的例子中,将为空的hold space附加到文件的每一行后面,所以结果是每一行后面多了一个空行
引申出:
sed ’/^$/d;G’
在文件的每一个非空行下面输出一个空行
sed ’/^$/d;G;G’
在文件的每一个非空行下面输出两个空行
代码:
$ cat foo
11111111111111
22222222222222
33333333333333
44444444444444
55555555555555
$ sed ’/^$/d;G’ foo
11111111111111
22222222222222
33333333333333
44444444444444
55555555555555
注:有时会有一些由空格符或者TAB组成的空行,前面的正则式 ^$ 就不能匹配到这样的行,则可以这样
sed ’/[[:space:]]/d;G’
例子二
sed ’/regex/{x;p;x;}’
在匹配regex的所有行前面插入一个空行
代码:
$ cat foo
11111111111111
22222222222222
test33333333333333
44444444444444
55555555555555
$ sed ’/test/{x;p;x;}’ foo
11111111111111
22222222222222
test33333333333333
44444444444444
55555555555555
解释:
sed 中 x 的用法
The exchange function interchanges the contents of the pattern space and the holding area. The maximum number of addresses is two.
即交换保持空间hold space和模式空间pattern space的内容
sed 中 p 的作用是把模式空间复制到标准输出。
分析一下该命令执行过程中保持空间和模式空间的内容
命令 保持空间 模式空间
x 执行前:null 执行后:test\n 执行前:test\n 执行后:null
p 执行前:null 执行后:test\n 执行前:test\n 执行后:null 输出一个空行
x 执行前:test\n 执行后:null 执行前:null 执行后:test\n
(注:把test所在的行简写为test了)
引申:
可以试验一下 sed ’/test/{x;p;}’ foo 或者 sed ’/test/{p;x;}’ foo 等,看看结果,体会两个空间的变化
相应的:
sed ’/regex/G’ 是在匹配regex的所有行下面输出一个空行
sed ’/regex/{x;p;x;G;}’ 是在匹配regex的所有行前面和下面都输出一个空行
例子三
sed ’n;G;’
在文件的偶数行下面插入一个空行
代码:
$ cat foo
11111111111111
22222222222222
33333333333333
44444444444444
55555555555555
$ sed ’n;G;’ foo
11111111111111
22222222222222
33333333333333
44444444444444
55555555555555
解释:
sed 中 n 的用法:将模式空间拷贝于标准输出。用输入的下一行替换模式空间。
执行 n 以后将第一行输出到标准输出以后,然后第二行进入模式空间,根据前面对 G 的解释,会在第二行后面插入一个空行,然后输出;再执行 n 将第三行输出到标准输出,然后第四行进入模式空间,并插入空行,依此类推
相应的:
sed ’n;n;G’ 表示在文件的第 3,6,Array,12,... 行后面插入一个空行
sed ’n;n;n;G’ 表示在文件的第 4,8,12,16,... 行后面插入一个空行
sed ’n;d’ 表示删除文件的偶数行
例子四
sed ’$!N;$!D’
输出文件最后2行,相当于 tail -2 foo
代码:
$ cat foo
11111111111111
22222222222222
33333333333333
44444444444444
55555555555555
$ sed ’$!N;$!D’ foo
44444444444444
55555555555555
解释:
D 删除模式空间内第一个 newline 字母 \n 前的资料。
N 把输入的下一行添加到模式空间中。
sed ’$!N;$!D’ : 对文件倒数第二行以前的行来说,N 将当前行的下一行放到模式空间中以后,D 就将模式空间的内容删除了;到倒数第二行的时候,将最后一行附加到倒数第二行下面,然后最后一行不执行 D ,所以文件的最后两行都保存下来了。
还有 N 的另外一种用法
代码:
$ sed = foo | sed N
1
11111111111111
2
22222222222222
3
33333333333333
4
44444444444444
5
55555555555555
$ sed = foo | sed ’N;s/\n/ /’
1 11111111111111
2 22222222222222
3 33333333333333
4 44444444444444
5 55555555555555
解释:
N 的作用是加上行号,可以用于格式化输出文件
例子五
sed ’1!G;h;$!d’
sed -n ’1!G;h;$p’
将文件的行反序显示,相当于 tac 命令(有些平台没有这个命令)
代码:
$ cat foo
11111111111111
22222222222222
33333333333333
$ sed ’1!G;h;$!d’ foo
33333333333333
22222222222222
11111111111111
$ sed -n ’1!G;h;$p’ foo
33333333333333
22222222222222
11111111111111
解释:
sed 中 h 用法:h
The h (hold) function copies the contents of the pattern space into a holding area, destroying any previous contents of the holding area.
意思是将模式空间的内容保存到保持空间中去
sed 中的 d 表示删除模式空间。
1!G表示除了第一行以外,其余行都执行G命令;$!d表示除了最后一行以外,其余行都执行d命令。
看一下sed ’1!G;h;$!d’命令执行过程中保持空间与模式空间的变化:
命令 保持空间 模式空间
第一行 h;d 执行前:null 执行后:1111\n 执行前:1111\n 执行后:null
第二行 G;h;d 执行前:1111 执行后:2222\n1111\n 执行前:2222\n 执行后:null
第二行 G;h 执行前:2222\1111\n 执行后:3333\n2222\n\1111\n 执行前:3333\n 执行后:3333\n2222\n\1111\n
(注:把各个行简写了)
这样输出以后就是文件的反序了。
题外话:在vi中对一个文件进行反序显示的命令是 :g/./m0 , 意思是按照文件正常顺序每找到一行,就把该行放到文件的最上面一行去,这样循环一下正好把文件的行反序显示了。
sed 学习笔记(与大家共勉)
声明:这些代码只是为了学习和理解sed命令而为之,并不代表问题的唯一解或最佳解,希望各位拍砖
参考资料:<sed&awk.pdf>等
一. 替换
1.神奇变换(y命令的使用)
- sed 'y/ori_letter_list/target_letter_list/' filename
复制代码
- cat filename
- 1234567890
- 2345678901
- 3456789012
- 4567890123
复制代码
测试
将文件中1换成A
将文件中2换成B
...
将文件中0换成J
- sed 'y/1234567890/ABCDEFGHIJ/' filename
- ABCDEFGHIJ
- BCDEFGHIJA
- CDEFGHIJAB
- DEFGHIJABC
复制代码
注意变换关系是按两个list的位置对应变换,y是一个管局命令,拒绝使用后缀flag/g
list1:1234567890
list2:ABCDEFGHIJ
下面再作一个与前例相反的变换
- sed 'y/0987654321/ABCDEFGHIJ/' filename
- JIHGFEDCBA
- IHGFEDCBAJ
- HGFEDCBAJI
- GFEDCBAJIH
复制代码
2.替换每行第一个匹配
- sed 's/regexpr/anyword/' filename
- sed 's/regexpr/anyword/1' filename
复制代码
举例:
QUOTE:
cat filename
1234567890 2345678901
3456789012 4567890123
sed 's/5/五/' filename
1234五67890 2345678901
34五6789012 4567890123
3.替换每行第n(如果有的话)个匹配
- sed "s/regexpr/anyword/${n}" filename
- cat filename
- 111111111111111111
- 222222222222222222
- 333333333333333333
- 444444444444444444
- 举例
- sed "s/4/ 四 /8" filename
- 111111111111111111
- 222222222222222222
- 333333333333333333
- 4444444 四 4444444444
复制代码
4.替换每行所有匹配
- cat filename
- 1234567890 2345678901
- 3456789012 4567890123
复制代码
- 举例:
- sed 's/3/三/g' filename
- 12三4567890 2三45678901
- 三456789012 456789012三
复制代码
二.行号处理
1.为文件加行号
- sed = filename|sed 'N;s/\n/:/'
- cat filename
- 111111111111111111
- 222222222222222222
- 333333333333333333
- 444444444444444444
复制代码
举例
- sed = filename|sed 'N;s/\n/:/' filename
- 1:111111111111111111
- 2:222222222222222222
- 3:333333333333333333
- 4:444444444444444444
复制代码
2.仅为文件中的正文行加行号
- sed /./= a|sed '/./N;s/\n/:/'
复制代码
举例
- cat filename
- 111111111111111111
- 222222222222222222
- 333333333333333333
- 444444444444444444
- sed /./= a|sed '/./N;s/\n/:/' filename
- 1:111111111111111111
- 3:222222222222222222
- 4:333333333333333333
- 6:444444444444444444
复制代码
三.字串翻转
- sed '/\n/!G;s/\(.\)\(.*\n\)/&\2\1/;//D;s/.//'
复制代码
举例
- echo 1234567890|sed '/\n/!G;s/\(.\)\(.*\n\)/&\2\1/;//D;s/.//'
- 0987654321
复制代码
四.选择性输出
1.打印文档奇数行(隔行输出)
- sed 'n;d'
- sed 'x;$!N;x'
- sed -n 'p;n'
- 1
- 3
- 5
- 7
复制代码
2.打印偶数行(隔行输出)
- sed -n 'n;p'
- sed '1d;n;d;'
- 2
- 4
- 6
- 8
复制代码
3.删除连续重复行(大量使用了pattern space 文件太大时要注意)
- sed '$!N; /^\(.*\)\n\1$/!P; D'
- #使用 $!N 要当心内存溢出
复制代码
举例
- cat file
- 111111111111111111
- 222222222222222222
- 222222222222222222
- 333333333333333333
- 444444444444444444
- 444444444444444444
- 444444444444444444
- 444444444444444444
- 444444444444444444
- sed '$!N; /^\(.*\)\n\1$/!P; D' filename
- 111111111111111111
- 222222222222222222
- 333333333333333333
- 444444444444444444
复制代码
4.合并上下行并以空格相分隔
- sed '$!N;s/\n/ /'
复制代码
举例
- cat file
- 1234567890
- 0987654321
- 执行命令后
- 1234567890 0987654321
复制代码
5.将以\符号结尾的行与下行合并并以空格分隔(拼接断行)
- sed -e :a -e '/\\$/N; s/\\\n/ /; ta'
复制代码
举例
- cat filename
- 1 111111111111111111\
- 2 222222222222222222
- 3 333333333333333333\
- 4 444444444444444444
- sed -e :a -e '/\\$/N; s/\\\n/ /; ta' filename
- 1 111111111111111111 2 222222222222222222
- 3 333333333333333333 4 444444444444444444
复制代码
6.按关键字拼接行
如果某行以=开始,则合并到上一行并替代=为空格
- sed -e :a -e '$!N;s/\n=/ /;ta' -e 'P;D'
复制代码
举例
- cat file
- 111111111111111111
- 222222222222222222
- =333333333333333333
- 444444444444444444
- sed -e :a -e '$!N;s/\n=/ /;ta' -e 'P;D' filename
- 111111111111111111
- 222222222222222222 333333333333333333
- 444444444444444444
复制代码
7.输出匹配行的下一行
- sed -n '/regexpr/{n;p;}' filename
复制代码
举例
- cat filename
- 1 111111111111111111
- 2 222222222222222222
- 3 333333333333333333
- 4 444444444444444444
- sed -n '/^3/{n;p;}' filename
- 4 444444444444444444
复制代码
8.显示匹配行的行号并输出匹配行的上行、匹配行、下行
sed -n -e '/regexpr/{=;x;1!p;g;$!N;p;D;}' -e h
举例
- cat filename
- 1 111111111111111111
- 2 222222222222222222
- 3 333333333333333333
- 4 444444444444444444
- sed -n -e '/^3/{=;x;1!p;g;$!N;p;D;}' -e h filename
- 3 #匹配行的行号
- 2 222222222222222222 #上一行
- 3 333333333333333333 #匹配行
- 4 444444444444444444 #下一行
复制代码
9.删除文档中某标志区域内的关键字匹配行
删除文档中从being开到end结束的块中包含myword的行
- sed '/^begin/,/^end/{/myword/d;}' filename
复制代码
QUOTE:
cat filename
myword
begin
myword
Number!
myword
Number!
myword
Number!
myword
Number!
end
myword
Number!
测试
QUOTE:
myword
begin
Number!
Number!
Number!
Number!
end
myword
Number!
五.字串解析
1.从字串中解析出两个子串(前2各字符和后9个字符)
- echo "WeLoveChinaUnix"|sed -e 'H;s/\(..\).*/\1/;x;s/.*\(.\{9\}\)$/\1/;x;G;s/\n/ /'
- We ChinaUnix
复制代码
2.分解日期串
- echo 20030922|sed 's/\(....\)\(..\)\(..\)/\1 \2 \3/'|read year month day
- echo $year $month $day
- 2003 09 22
复制代码
sed 学习笔记(与大家共勉)
QUOTE: 原帖由 "binary" 发表:
复制代码
QUOTE: cat filename.sed
QUOTE: sed -f filename.sed filename
|
- n 读入下一笔(下一行)资料。
- N 添加下一笔(下一行)资料到 pattern space。
|
| |||
IBM“人机大战”趣味问答| 2010您最想感谢的CUer是谁? |微软开发资料免费下载|TCP/IP实现刨根究底大讨论! |
| |||
|
| |||
admirer(admirer) admirer(admirer)当前离线 UID 13301597 帖子 精华 积分 4489 可用积分 4489 信誉积分 100 专家积分 0 (本版:) 空间积分 0 阅读权限 100 性别 男 来自 西北小镇 在线时间 8 小时 注册时间 2002-04-30 最后登录 2010-12-03
帖子 主题 精华 可用积分 4489 专家积分 0 (本版:0) 来自 西北小镇 在线时间 8 小时 注册时间 2002-04-30 最后登录 2010-12-03 状态:...当前离线... | 14楼 发表于 2003-09-29 10:31 | 只看该作者 sed 学习笔记(与大家共勉)
|
| ||
|
sed -n -e '/test/{=;x;1!p;g;$!N;p;D;}' -eh file
=:Place the current line number on the standard output as a line.
x:Exchange the contents of the pattern and hold spaces.
p:Print. Copy the pattern space to the standard output.
g:Replace the contents of the pattern space by the contents of the hold space.
N:Append the next line of input to the pattern space with an embedded new-line.
(The current line number changes.) If the end of input is reached,the N command verb shall branch to the end of the script
p:Print. Copy the pattern space to the standard output.
D:Delete the initial segment of the pattern space through the firstnew-line.Start the next cycle. (See the N command below.)
h:Replace the contents of the hold space by the contents of the pattern space.
楼主能不能解释一下上面的命令,我就是没看出来sed是怎么存储匹配行的上面一行的?
sed 学习笔记(与大家共勉)
echo "WeLoveChinaUnix"|sed -e 'H;s/\(..\).*/\1/;x;s/.*\(.\{9\}\)$/\1/;x;G;s/\n/ /' |
sed 学习笔记(与大家共勉)
|
| |||
__________________________________
IBM“人机大战”趣味问答| 2010您最想感谢的CUer是谁? |微软开发资料免费下载|TCP/IP实现刨根究底大讨论! |
| |||
|
| |||
梦蓝当前离线 UID 12537180 帖子 精华 积分 306 可用积分 306 信誉积分 100 专家积分 0 (本版:) 空间积分 0 阅读权限 20 性别 男 在线时间 17 小时 注册时间 2004-08-06 最后登录 2010-11-28
帖子 主题 精华 可用积分 306 专家积分 0 (本版:0) 在线时间 17 小时 注册时间 2004-08-06 最后登录 2010-11-28 状态:...当前离线... | 32楼 发表于 2005-03-16 13:44 | 只看该作者 sed 学习笔记(与大家共勉)
|
| ||
|
QUOTE:
原帖由 "lozity" 发表:
sed -n -e '/test/{=;x;1!p;g;$!N;p;D;}' -e h file
=:Place the current line number on the standard output as a line.
x:Exchange the contents of the pattern and hold spaces.
p:Print. Copy the patt..........
在匹配test之前,运行了h命令,这就是在keep space保存了前一行的信息
在匹配test时,运行了x p命令,这就是打印了前一行的信息
sed 学习笔记(与大家共勉)
sed /./= a|sed '/./N;s/\n/:/' |
|
| |||
IBM“人机大战”趣味问答| 2010您最想感谢的CUer是谁? |微软开发资料免费下载|TCP/IP实现刨根究底大讨论! |
| |||
|
| |||
3楼楼长 r2007当前离线 3楼楼长 UID 45358 帖子 精华 积分 904 可用积分 904 信誉积分 100 专家积分 30 (本版:) 空间积分 4 阅读权限 20 性别 男 在线时间 3860 小时 注册时间 2003-11-27 最后登录 2011-03-23
帖子 主题 精华 可用积分 904 专家积分 30 (本版:0) 在线时间 3860 小时 注册时间 2003-11-27 最后登录 2011-03-23 状态:...当前离线... | 43楼 发表于 2005-03-25 12:48 | 只看该作者 sed 学习笔记(与大家共勉)
|
| ||
|
sed 学习笔记(与大家共勉)
补充一下 n和N |
|
| |||
IBM“人机大战”趣味问答| 2010您最想感谢的CUer是谁? |微软开发资料免费下载|TCP/IP实现刨根究底大讨论! |
| |||
|
| |||
bjwangc当前离线 UID 14199287 帖子 精华 积分 516 可用积分 516 信誉积分 0 专家积分 0 (本版:) 空间积分 0 阅读权限 20 在线时间 2 小时 注册时间 2008-02-22 最后登录 2010-05-10
帖子 主题 精华 可用积分 516 专家积分 0 (本版:0) 在线时间 2 小时 注册时间 2008-02-22 最后登录 2010-05-10 状态:...当前离线... | 50楼 发表于 2008-03-04 17:04 | 只看该作者
|
| ||
|