这是我在这个网站上的第一篇文章。我可能不是很容易使用awk或sed语言的问题。在我的文件中是这样的数据:
A
B
C
[Start]D
E
F
[/End]
G
...
[Start]H
I
J
[/End]
...
K
我需要以下结果:
A
B
C
[Open]D E F[/Close]
G
...
[Open]H I J[/Close]
...
K
目前我还没有使用awk代码:
BEGIN {
step=0
}
/[\/End]/ {
if(step==3) print "[/Close]"
step=0
}
step==2 {
print
step=3
}
step==1{
print
step=2
}
/[Start]/ {
print "[Begin]"
step=1
}
step=0{
print
}
非常感谢你的回答。我希望能在这儿待一会儿。干杯! P上。
答案 0 :(得分:2)
使用sed,你可以写(GNU sed语法,对于BSD sed见下文):
sed '/\[Start\]/ { s//[Open]/; :a \,\[/End\],! { s/\n/ /; N; ba }; s,,[/Close],; s/\n// }' filename
这应理解如下:
/\[Start\]/ { # If a line contains [Start]
s//[Open]/ # replace it with [Open] (an empty regex reattempts the most
# recently used regex, which was \[Start\])
:a # jump label for looping
\,\[/End\],! { # Until we find [/End]
s/\n/ / # replace newlines with spaces (this does nothing the first
# time around, but since we don't want to replace the last
# newline with a space but an empty string, we have to
# isolate it somehow; this works for that
N # fetch next line, append it to what we already have
ba # go back to a
}
s,,[/Close], # replace the [/End] we just found with [/Close]
s/\n// # and replace the last newline with nothing, to get the
# spaces right.
}
请注意,要使用BSD sed工作,必须稍微修改一下调用:
sed -e '/\[Start\]/ { s//[Open]/; :a' -e '\,\[/End\],! { s/\n/ /; N; ba' -e '}; s,,[/Close],; s/\n// }' filename
这是因为BSD sed不像GNU sed那样以分号终止标签名称。除了在标签名称之后拆分代码的-e
之外,它是相同的代码。
进一步请注意,只有[Start] .. [/End]
标记未嵌套时,此方法才有效。如果它们是,你将要抛弃sed
和awk
并至少使用Perl(它支持regexes 1 中的递归)。
1 好吧,它称之为“正则表达式”;它有点用词不当,因为它们并不局限于普通语言,而Perl对它们的所有东西都是如此。重点是:嵌套标签不再是常规语言,所以你需要/想要它的东西。
答案 1 :(得分:2)
$ cat tst.awk
sub(/^\[Start\]/,"[Open]") { ors=ORS; ORS=OFS }
sub(/^\[\/End\]/,"[Close]") { ORS=ors }
{ print }
$ awk -f tst.awk file
A
B
C
[Open]D E F [Close]
G
...
[Open]H I J [Close]
...
K
如果你在每个" [关闭]之前关心额外的空间"我们可以做一些不同的事情,但它会有点复杂。例如:
$ cat tst.awk
sub(/^\[Start\]/,"[Open]") { f=1; rec=$0; next }
sub(/^\[\/End\]/,"[Close]") { f=0; $0=rec $0 }
f { rec = rec OFS $0; next }
{ print }
$ awk -f tst.awk file
A
B
C
[Open]D E F[Close]
G
...
[Open]H I J[Close]
...
K
答案 2 :(得分:1)
这个awk会完成大部分操作,但会在[\ Close]
之前留空awk '/Start/{ORS=FS} /End/{ORS=RS} sub(/Start/,"Open") sub(/End/,"Close") 1' file
很容易在另一个传递中修剪它(管道先前输出到此脚本)
awk 'sub(/ \[/,"\[") 1'