在边界之间查找和移动文字

时间:2016-10-13 07:21:51

标签: regex shell text awk sed

我有一个巨大的文本文件,其中包含以这种格式的文本集合:

<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="....

之间的文字

2 个答案:

答案 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行。