bash(sed或awk首选)删除第一个和最后一个实例之间的所有内容

时间:2012-12-10 20:54:29

标签: regex bash sed awk

我对sed非常熟悉,但我不太了解awk,我不知道如何解决这个问题。我已经google了一段时间但到目前为止没有运气。情况就是这样:我有一个包含组和部分的大文件,如下所示:

<A1>
  some nr of lines
</A1>
<A2>
  some nr
  of lines
</A2>
<B1>
  some
  nr of
  lines
</B1>
<B2>
  some nr of lines
</B2>
<B3>
  bla
</B3>
<C1>
  bla
</C1>
<C2>
  bla
</C2>

现在问题是组的数量可以改变,部分的数量可以改变,每个部分的行数可以改变。例如,A部分可能转到25,B部分可能转到8,依此类推。我需要做的是删除某些群组的所有条目,在上面的示例中,我想删除<B*>中的所有内容,并留下以下内容:

<A1>
  some nr of lines
</A1>
<A2>
  some nr
  of lines
</A2>
<C1>
  bla
</C1>
<C2>
  bla
</C2>

此外,我想删除几个部分(虽然这些部分可以在单独的运行中),例如,如果文件从A1转到R123,我想删除B *,F *,M *等等。

如果有类似的事情已经被问过并在某处我回答道歉,我确实在发布之前找到了解决方案。

谢谢!

2 个答案:

答案 0 :(得分:6)

使用sed:

sed '/<B1>/,/<\/B3>/d' infile

这意味着找到从<B1>开始到</B3>结束的文本范围,并从sed的输出中删除它。 (这意味着sed将在stdout上打印其余文件)

编辑:这也适用于您的情况:

sed '/<B[0-9]*>/,/<\/B[0-9]*>/d' 

答案 1 :(得分:1)

我认为你所寻找的是这样的:

awk -v rmv="AC" 'BEGIN{
   gsub(/./,"|&",rmv)
   sub(/$/,")[0-9]+>$",rmv)
   start = end = rmv
   sub(/^\|/,"^<(",start)
   sub(/^\|/,"^</(",end)
}
$0 ~ start { f=1 }
!f
$0 ~ end   { f=0 }
' file

Just populate the "rmv" variable with the list of all the sections you want removed:

$ awk -v rmv="B" '...'
<A1>
  some nr of lines
</A1>
<A2>
  some nr
  of lines
</A2>
<C1>
  bla
</C1>
<C2>
  bla
</C2>
$ awk -v rmv="AC" '...'
<B1>
  some
  nr of
  lines
</B1>
<B2>
  some nr of lines
</B2>
<B3>
  bla
</B3>
$