`
ych4865
  • 浏览: 6570 次
  • 性别: Icon_minigender_1
  • 来自: 杭州
最近访客 更多访客>>
社区版块
存档分类
最新评论

sed学习笔记-进阶篇

    博客分类:
  • sed
sed 
阅读更多
-----------------------
进阶部分:

多行模式空间:对于多行内的数据进行匹配处理;

·N(Next)命令获取下一行到模式空间。
获取到的多行模式空间,使用\n匹配多行间的换行符,
^匹配模式空间(可多行)的首字符,$匹配模式空间(可多行)的末字符.

·对于一行内满足条件的先进行匹配,之后进行行间的匹配,
可以保证一行内有两个owner的情况下的匹配:
[root@localhost ~]# sed -f owner.sed sedtest.log
the installation guide
for xx
the installation guide shipped with xx
including the installation guide
and xx
the installation guide is xx

[root@localhost ~]# cat sedtest.log
the owner and operator
guide for xx
the owner and operator guide shipped with xx
including the owner and
operator guide and xx
the owner and operator guide is xx

[root@localhost ~]# cat owner.sed
s/owner and operator guide/installation guide/
/owner/{
N
s/ *\n/ /
s/owner and operator guide */installation guide\
/
}

·不使用脚本的第一行,将一行内全部匹配的先处理的情形时,
出现问题的分析:
[root@localhost ~]# cat owner.sed
/owner/{
N
s/ *\n/ /
s/owner and operator guide */installation guide\
/
}
#未先进行一行内先处理语句。
[root@localhost ~]# cat sedtest.log
the owner and operator
guide for xx
the owner and operator guide shipped with xx
including the owner and
operator guide and xx
the owner and operator guide is xx

[root@localhost ~]# sed -f owner.sed sedtest.log(结果中在#行加入了解释)
the installation guide
for xx
#上面处理的是源文件的1-2行,即第一次的匹配。
the installation guide
shipped with xx including the owner and
#上面处理的是源文件的3-4行,Next命令将第二个owner加入模式空间,在第一个owner匹配后,直接被打印,清除模式空间。
operator guide and xx
#该行不匹配owner,直接被打印,清除模式空间。
the installation guide
is xx
#匹配最后一个owner,并打印。
#总之,有第3个owner未匹配这个问题;以及最后空行被取消也是一个问题。

·使用Next时,最末行的注意事项。
#N在执行到最后行时,会出现错误,需要使用$!N:
[root@localhost ~]# cat sedtest.log
the owner and operator
guide for xx
the owner and operator guide shipped with xx
[root@localhost ~]# sed -f owner.sed sedtest.log
the installation guide
for xx
the installation guide
shipped with xx
[root@localhost ~]# cat owner.sed
/owner/{
$!N
s/ *\n/ /
s/owner and operator guide */installation guide\
/
}
#未使用$!时,未对最后行进行处理:
[root@localhost ~]# sed -f owner.sed sedtest.log
the installation guide
for xx
the owner and operator guide shipped with xx
[root@localhost ~]# cat owner.sed
/owner/{
N
s/ *\n/ /
s/owner and operator guide */installation guide\
/
}

·D(Delete)命令:
进行多行模式空间内的删除动作;
和d命令的区别:
d是对整个模式空间的内容进行删除处理,
而D是对模式空间的首行进行处理。
一个例子:
测试的文件,需要将大于1行的连续空行删除成1行。
[root@localhost ~]# cat -A del_test.log
1spaceline:$
$
2spaceline:$
$
$
3spaceline:$
$
$
$
end$
使用d进行多行模式空间删除:
[root@localhost ~]# cat del.sed
/^$/{
N
/^\n$/d
}
#得出的结果,出现2行连续时都被删除:
[root@localhost ~]# sed -f del.sed del_test.log
1spaceline:

2spaceline:
3spaceline:

end

#变更d为D:
[root@localhost ~]# cat del.sed
/^$/{
N
/^\n$/D
}
#结果是符合我们的要求的:
[root@localhost ~]# sed -f del.sed del_test.log
1spaceline:

2spaceline:

3spaceline:

end

·P(Print)多行模式中的打印命令:
打印多行模式空间中的第一行;
一般应用在N之后,D之前,用于输出处理行(一般时第一行),
由于替换等处理后,接着需要删除该行后处理下一行,所以不会处理输出,所以需要使用P;
一般使用N-P-D的循环,来实现逐行进行加入处理先行末尾和后行行首结合匹配的功能;
而且可实现后行可以再次开始匹配的功能,因为是逐行删除的。
一个例子:
#在行末的UNIX和下行前system间加入OS;测试文件:
[root@localhost ~]# cat ptest.log
the UNIX
system is xx,UNIX
system is yy,
the UNIX system.
#脚本:使用了N-P-D循环:
[root@localhost ~]# cat ptest.sed
/UNIX$/{
N
/\nsystem/{
s// OS&/
P
D
}
}
[root@localhost ~]# sed -f ptest.sed ptest.log
the UNIX OS
system is xx,UNIX OS
system is yy,
the UNIX system.


·保持空间:
保持空间:用于临时存储模式空间的数据;
对模式空间和保持空间进行操作的命令:
Hold:H和h,将模式空间数据追加或拷贝到保持空间;(在原有内容后先加换行符)
Get:G和g,将保持空间数据追加或拷贝到模式空间;(在原有内容后先加换行符)
Exchange:x,将模式空间数据和保持空间的数据进行交换。

一个简单的数据切换的例子:
[root@localhost ~]# sed -f space.sed spacetest.log
22
11
222
111
[root@localhost ~]# cat space.sed
/1/{
h
d
}
/2/{
G
}
[root@localhost ~]# cat spacetest.log
11
22
111
222
#将含1行和含2行进行交换;将含1行放入保持空间后删除,以禁止输出;
获取到含2行时,追加获取保持的含1行,输出;

一个替换一类字符为统一大写的字符的例子(具体字符可以不指定,只要指定具体位置即可)
[root@localhost ~]# sed -f matchspace.sed matchspace.log
find the MATCH statement
consult the GET statement
using the READ statement
[root@localhost ~]# cat matchspace.log
find the Match statement
consult the get statement
using the ReaD statement
[root@localhost ~]# cat matchspace.sed
/the .* statement/{
h
s/.* the \(.*\) statement.*/\1/
y/abcdefghijklmnopqrstuvwxyz/ABCDEFGHIJKLMNOPQRSTUVWXYZ/
G
s/\(.*\)\n\(.* the \).*\( statement.*\)/\2\1\3/
}
#先找到the .. statement相关语句,将原语句保存到保持空间内;
通过s获取到待替换单词;使用y进行小写转换为大写;
将保持空间原数据追加获取到模式空间;
通过s将多行模式空间内的需要的3段进行分别分离,再在替换部分进行重新组合。(重点)

一个进行空间内容相互交换的例子:
[root@localhost ~]# sed -f html.sed htmltest.log
<p>start line
a space line as:</p>

<p>end line
last space line as:</p>

[root@localhost ~]# cat htmltest.log
start line
a space line as:

end line
last space line as:

[root@localhost ~]# cat html.sed
/^$/!{
H
d
}
/^$/{
x
s/^\n/<p>/
s/$/<\/p>/
G
}
#将非空行保存到保持空间;遇到空行,进行x交换;进行匹配替换后,再读入空行进行输出。

以上的例子在末行不为空行时会出现不输出最后一个后的内容。
为解决这个问题:
[root@localhost ~]# sed -f html.sed htmltest.log
<p>start line
a space line as:</p>

<p>end line
last space line as:</p>

[root@localhost ~]# cat htmltest.log
start line
a space line as:

end line
last space line as:
[root@localhost ~]# cat html.sed
${
/^$/!{
        H
        s/.*//
        }
}
/^$/!{
H
d
}
/^$/{
x
s/^\n/<p>/
s/$/<\/p>/
G
}
#加入前面的一个部分,使用$匹配文件的最后一行;
如该行不是空行,则将内容保存到保持空间;再将模式空间的内容变为空行,
则向下达到空行流程,交换内容,加入空行输出。(可以看到有一个缺陷:在原文件基础上末行后加了一个空行)

·流控制命令:
流控制命令::标签;b分支命令;t测试命令;
:label:定义标签名;
/pattern/b <label>:匹配模式后,如有label,程序跳到label后执行;如无,直接跳到脚本末尾;
/address/t <label>:如匹配行的s命令执行成功,则执行t(可有或无label)

b的使用模式:
do-while形式:
:top
command1
/pattern/b top
command2

if(条件符合0)形式:
/pattern/b end
comand1
:end
comand2

if-else形式:
/pattern/b docmd2
comand1
b
:docmd2
comand2

·关于流控制,参考的一个例子:
#跨行将@f1(..),改为\fB..\fB
[root@localhost ~]# cat streamtest.log
start one line test:
start @f1(test1) and @f1(test2) end;
start multi line test:
start @f1(testtest
add1
add2
add3
endadd testend)
all end
[root@localhost ~]# sed -f stream.sed streamtest.log
start one line test:
start \fBtest1\fB and \fBtest2\fB end;
start multi line test:
start \fBtesttest
add1
add2
add3
endadd testend\fB
all end
[root@localhost ~]# cat stream.sed
:begin
/@f1(\([^)]*\))/{
s//\\fB\1\\fB/g
b begin
}
#查找一行内存在的所有符合模式项,使用b begin来循环匹配替换。
/@f1(.*/{
N
s/@f1(\([^)]*\n[^)]*\))/\\fB\1\\fB/g
t again
b begin
}
#查找多行上的符合模式项,如无匹配,使用b again来循环读入下一行;匹配成功走t again。
:again
P
D
#again后操作:如替换成功一次,则打印第一行,删除第一行,后续行继续进行匹配。

·一个比较综合的例子:(对于两行内的模式进行匹配)
#测试文件,需要查找关键字“I love apple”
[root@localhost ~]# cat fintest.log
the first line:test for first line,I love apple,end
the second line:test for second line,
I love apple,end
the fourth line:test for two lines,I love
apple,end
the sixth line:all end
#测试结果:
[root@localhost ~]# sed -f fin.sed fintest.log
the first line:test for first line,I love apple,end
I love apple,end
the fourth line:test for two lines,I love
apple,end
#脚本:(为了便于理解,直接在脚本内使用#号开始解释)
[root@localhost ~]# cat fin.sed
/I love apple/b
#对读入的第一行进行匹配,如匹配,跳出,打印。
$!N
#如上行未匹配,对于非最后行,读入下一行。
h
#保持到保持空间。
s/.*\n//
#去除第一行,保留第二行。
/I love apple/b
#对第二行进行匹配,如匹配,跳出,打印。
g
#如上行未匹配,读入保持空间内容。
s/ *\n/ /
#去除两行间的换行符和可能有的多余空格(类似合并为一行)
/I love apple/{
g
b
}
#对处理后的合并行进行匹配,如匹配,输出原始的两行,跳出,打印。
g
D
#如3种情况都未匹配,删除第一行,继续进行。

·题外话:
上面的例子:
修改文件:
[root@localhost ~]# cat fintest.log
xx
the second line:test for second line,
the fourth line:test for two lines,I love
apple,end
the sixth line:all end
[root@localhost ~]# sed -f fin.sed fintest.log
the fourth line:test for two lines,I love
apple,end
#感觉会有second line也被打印的问题,结果没有这样的问题,暂时不知道原因。

·参考:
sed & awk:Doughherty & Robbins.
分享到:
评论

相关推荐

Global site tag (gtag.js) - Google Analytics