使用Sed将输入解析为用花括号括起来的块

时间:2015-10-16 02:06:16

标签: regex awk sed

两个文件:

档案1

{
foo
}
{
bar
}

文件2

foo
}
{
bar
}

(唯一的区别是文件1以开放大括号开始)

以下表达式适用于文件2,但不适用于文件1,为什么? (以及如何解决?):

sed '1!N; s/}\n{/},\n{/' < file1 or file2

我不知道为什么打开大括号,匹配前2行会导致这种行为。我想知道为什么sed被绊倒以及如何解决它的原因。但是,除了sed之外,我还可以通过其他方式在,之间插入}\n{

4 个答案:

答案 0 :(得分:4)

这是你想要的(使用GNU awk进行多字符RS):

$ awk -v RS='}\n{' '{ORS=(RT?"},\n{":"")} 1' file1
{
foo
},
{
bar
}

$ awk -v RS='}\n{' '{ORS=(RT?"},\n{":"")} 1' file2
foo
},
{
bar
}

答案 1 :(得分:3)

它不是开口支撑,它是额外的线。将任何放在该行上(即使没有),您的脚本就会停止工作。

您的脚本严格基于对。它仅在结束ttk::style element create pin vsapi EXPLORERBAR 3 { {pressed !selected} 3 {active !selected} 2 {pressed selected} 6 {active selected} 5 {selected} 4 {} 1 } ttk::style layout Explorer.Pin {Explorer.Pin.pin -sticky news} pack [ttk::checkbutton .pin -style Explorer.Pin] 落在偶数行时才有效。

您的Sed脚本显示} - 对于不在第一行的每一行,将 next 行读入模式空间,然后尝试1!N转化

然后脚本结束,Sed打印模式空间,丢弃它,并读取下一行。你只能从第二行开始一次配对两行。

的文件
s///

也不会被正确修改,但是

}
{

意愿。

这个Sed命令

f
}
{

适用于不包含sed '/}$/{N;s/}\n{/},\n{/}' 的文件(它会错过这些文件)。

对于更强大的内容,您需要}\n}\n{之类的内容或awk更好的内容,而不是我想出更聪明的脚本。

答案 2 :(得分:2)

这可能适合你(GNU sed):

 sed '1b;$!N; s/}\n{/},\n{/;P;D' file

目前,您正在处理成对的行之后,您想要使用两行窗口遍历文件。 这将使两行窗口一次又一行地撞击文件的末尾,即它删除第一行但保留第二行然后将下一行附加到该行。要查看它是如何工作的(并且通常对所有sed脚本都有用),请使用l命令:

sed '1b;$!N;l;s/}\n{/},\n{/;P;D' file

答案 3 :(得分:1)

Etan Reisner's answer很好地解释了sed命令的问题。

通常,awk可以更轻松地解析跨越行

假设 GNU awkmawk,请尝试以下操作:

awk -v RS='\n}\n{' '/\}\n$/ { printf "%s", $0; next; } { printf "%s\n},\n{", $0 }' file

顶级域内的嵌套{...}序列是可以的,只要它们的结束} 缩进

  • RS='\n}\n{'表示输入被\n}\n{序列分成记录 - 跨行。
    • 注意:多字符RS值是POSIX standard扩展名,GNU Awk和Mawk恰好实现了这一点; BSD Awk,也用于OS X,
  • /\}\n$/仅匹配 last 记录,因为后面没有其他{
    • printf "%s", $0只是按原样打印;它的开头{(如果有的话)是在上一条记录的上下文中打印出来的,如果有的话。
  • 否则 - 第一个或任何内部记录 - 打印时在其结束,和下一个记录的开头}之间插入{{ printf "%s\n},\n{", $0 }