我想在以start开头并以End结尾的行之间的文件中搜索行范围,并用冒号替换换行符。我需要在SED或AWK中完成。
示例文件:
start
a
b
c
End
Start
a
b
c
End
Start
x
y
z
End
预期产出:
a:b:c
a:b:c
x:y:z
答案 0 :(得分:4)
这个简短的单行应该可以工作:
awk -v RS='Start|End' -v OFS=":" '$1=$1' file
包含您的数据:
kent$ cat f
Start
a
b
c
End
Start
a
b
c
End
Start
x
y
z
End
kent$ awk -v RS='Start|End' -v OFS=":" '$1=$1' f
a:b:c
a:b:c
x:y:z
答案 1 :(得分:1)
让我们试试awk
。
$ awk '/start/ || /Start/ {next} /End/ {print line; line=""; next} {if (line) {line=line":"} line=line$0}' file
a:b:c
a:b:c
x:y:z
/start/ || /Start/ {next}
在包含“开始”或“开始”的行上,跳过。/End/ {print line; line=""; next}
的行上End
,打印包含已加载信息的line
变量。删除var的值并转到下一行。{if (line) {line=line":"} line=line$0}
,继续在line
变量中加载数据。 if
条件是避免使用尾随:
。 /start/ || /Start/ {next}
可以缩减为这两种(thanks Jotne):
/start|Start/ {next}
/(s|S)tart/ {next}
答案 2 :(得分:1)
这是一个版本:
awk '/End/{print a;f=a=0} f {a=a?a":"$0:$0} /(S|s)tart/{f=1}' file
a:b:c
a:b:c
x:y:z
我猜第一个start
中有拼写错误,如果是这样,请使用:
awk '/End/{print a;f=a=0} f {a=a?a":"$0:$0} /Start/{f=1}' file
/End/{print a;f=a=0}
如果行包含End
打印a
,则将f
和a
设置为0
f {a=a?a":"$0:$0}
如果f
为真,请先将a
设为$0
进行首次运行,然后在下次运行时设为:$0
/Start/{f=1}
如果行Start
将f
设置为1
(true)
答案 3 :(得分:1)
如果开始和结束之间总是有3行:
grep -iv 'start\|end' file | paste -d: - - -
答案 4 :(得分:0)
sed -n '/Start/,/End/ {
/Start/ !{
/End/ !H
}
/End/ {
s/.*//
x
s/\n/:/g
s/://
p
}
}
/Start/,/End/ !p' YourFile
如果 start
和Start
应该工作,请Start
替换[sS]tart
(End
除[eE]nd
)在代码中
<强>释强>
除非特定请求
,否则请先打开sed而不打印ouptut/Start/,/End/ {
对于以Start
开头且以End
结尾的任何行块(在单独的行上)
/Start/ !{
/End/ !H
}
如果行不包含(!
)Start
而不是End
,则将该行添加(追加)到保留缓冲区(存储类型)
/End/ {
s/.*//
x
s/\n/:/g
s/://
p
}
到达包含End
End
)x
)保持缓冲区(存储了所有行的行)和工作缓冲区(可以操作且通常具有当前行的缓冲区):
更改所有新行(缓冲区包含交换后新行分隔的所有行):
(由于第一个附加插入新行)打印内容
/开始/,/结束/!p
对于!
和Start
之间的块之间的所有行(End
),请将其打印
答案 5 :(得分:0)
使用GNU awk的另一种方法:
$ gawk -v RS='\0' '{ gsub(/\n/,":"); gsub(/:End:Start:/,"\n"); gsub(/^start:|:End:$/,"") }1' file
a:b:c
a:b:c
x:y:z
此处发布的其他awk解决方案也很好。