使用SED删除地址范围的换行符

时间:2014-05-11 16:34:08

标签: regex sed

我在使SED脚本正常工作时遇到了一些困难。它似乎只适用于第一次出现。我基本上是UNIX初学者 - 请耐心等待。

数据文件如下所示:

exec cics 
end-exec.
exec cics 
send map
end-exec.
exec cics 
end-exec.

实际输出如下所示,并且只在第一次出现时才能正常工作:

exec cics end-exec.
exec cics 
send map
end-exec.
exec cics 
end-exec.

所需的输出应如下:

exec cics end-exec.
exec cics send map end-exec.
exec cics end-exec.

以" exec cics"开头的一切并以" end-exec"结束应该在一行上删除任何新行。

SED脚本如下:

/exec cics/,/end-exec/{
:a    
N
$!ba
s/\n//
}

我从这里获得了大括号内的代码:How can I replace a newline (\n) using sed?

我的初始脚本没有:a;N;$!ba。谁能看到我遗失或做错了什么?

3 个答案:

答案 0 :(得分:2)

您获得的结果可以通过仅替换第一个换行符来解释:

s/\n//

但是,即使您在全球范围内执行了替换,即使用了:

s/\n//g
你会得到:

exec cics end-exec. exec cics  send map end-exec. exec cics  end-exec.

因为$地址与文件中最后一次出现的匹配。

除非您匹配最后一行,否则不要分支到标签a,而是在遇到end-exec时不要分支。话说:

sed '/exec cics/,/end-exec/{:a;N;/end-exec/!ba;s/\n/ /g}' filename

会产生:

exec cics end-exec.
exec cics send map end-exec.
exec cics end-exec.

如果您的输入包含从exec cisc开始并以end-exec开头的连续块,则可以简化它:

sed ':a;N;/end-exec/!ba;s/\n/ /g' filename

答案 1 :(得分:1)

如果您想尝试awk

awk '{printf (/exec cics/ && NR>1?RS:"")"%s",$0} END {print ""}'
exec cics end-exec.
exec cics send mapend-exec.
exec cics end-exec.

如果行以exec cics开头而不是第一行,请在该行之前添加换行符 否则,只需将数据打印在一行中即可。

答案 2 :(得分:1)

sed脚本的这个修改版似乎可以完成这项工作:

/exec cics/,/end-exec/{
    :a
    /end-exec/! N
    s/\n/ /g
    t a
}

保存在文件sed.script中,并提供数据文件(data2):

exec cics
end-exec.
exec cics
send map
end-exec.
exec cics
end-exec.
exec cics
do this
and that
and tother
end-exec.

(任何数据行都没有尾随空白),然后我得到:

$ sed -f sed.script data2
exec cics end-exec.
exec cics send map end-exec.
exec cics end-exec.
exec cics do this and that and tother end-exec.
$

脚本有什么作用?

  1. 对于exec cicsend-exec之间的每个行范围,
  2. 设置标签a
  3. 如果图案空间不包含end-exec,则添加另一行。
  4. 用空格替换任何换行符。
  5. 如果有替换,请跳回标签a
  6. 在调试/设计时,我在t之后和}之前添加了几行:

    s/^/[[/
    s/$/]]/
    

    这有助于我了解如何使用各种其他版本的命令处理数据,包括原始版本;这些行在打印时被[[]]括起来。

    使用提供的BSD sed在Mac OS X 10.9.2 Mavericks上进行测试。