我有一个巨大的文本文件,其中包含以这种格式的文本集合:
<text id="1">
blah blah blah blah
blah blah
blah
</text>
<text id="2">
blah blah blah blah
blah blah
blah
</text>
<text id="3">
.....等。高达14.400
在某些时候我有这种情况:
<text id="XXX">
blah blah blah blah
blah blah
blah
</text>
**text out of bounds**
<text id="XXX">
blah blah blah blah
blah blah
我的意思是,在文本标签边界有文本的地方,我需要找到那些文本行并将它们移到前一个块的内部,所以得到的结构是这样的:
<text id="XXX">
blah blah blah blah
blah blah
blah
**text moved in bounds**
</text>
<text id="XXX">
blah blah blah blah
blah blah
换句话说,它不能是</text>
和<text id="....
答案 0 :(得分:1)
您可以使用此awk
脚本:
awk -v RS='<text id="[^"]*">[^<]*</text>' '
NF==0 && prev{print prev}
NF>0{
printf "%s", substr(prev, 1, index(prev, "</text>")-2)
printf "%s", $0
print "</text>"
}
{prev=RT}' file
记录分隔符RS
与<text id=...>
和</text>
之间的所有内容相匹配。因此,如果某些内容超出这两个标记,则会设置字段NF
的数量。
对于每条记录,变量prev
设置为包含当前RT
内容的记录终结符RS
。
如果2个标签NF==0
之间没有任何内容,则只需打印RT
中存储的上一个prev
的记录终结符。
如果超出界限(NF>0
),则在包含前一记录的结束标记之前打印所有内容。请注意index(...)-2
以避免打印结束标记的\n
和<
字符。最后打印结束标记。
答案 1 :(得分:1)
在您看到下一个</text
行或到达输入文件的末尾之前,不要打印<text
行:
$ cat tst.awk
/<\/text/ { end = $0 ORS; next }
/<text/ { printf "%s", end; end="" }
{ print }
END { printf "%s", end }
$ awk -f tst.awk file
<text id="XXX">
blah blah blah blah
blah blah
blah
**text out of bounds**
</text>
<text id="XXX">
blah blah blah blah
blah blah
这适用于任何操作系统上的任何awk,它将使用的唯一内存足以存储最长的</text
行。