如何使用awk打印每第n个比赛

时间:2011-03-07 13:16:45

标签: xml split awk

我正在尝试将大型xml文件拆分为几个较小的文件。我找到了将每个节点拆分成自己文件的解决方案:

awk '/<mono/{close("row"count".xml");count++}count{f="row"count".xml";print $0 > f}' file.xml 

上面的代码匹配每个“mono”节点并将其输出到文件名行{rownumber} .xml。如何将每20个匹配项打印到文件中?

2 个答案:

答案 0 :(得分:1)

保持两个计数 - 当前计数和重复计数。当重复计数模20处于适当的值(在所示代码中为0和1)时,仅执行当前活动(打印标记):

awk '/<mono/ { if (repeat++ % 20 == 0) { close("row"count".xml"); count++ } }
     count && repeat % 20 == 1 { f = "row"count".xml"; print $0 > f}' file.xml

第二个条件中的'== 1'条件有点凌乱;可能有更好的方法来处理这种逻辑。

请注意,您的代码也会将“<monotonous>”视为Mono。


将文件1中的记录1-20,文件2中的21-40等分组......

同样的一般想法适用...你有一个文件号和一个匹配的记录号,你可以适当地处理它们。经过测试的代码:

awk '/<mono/ {   if (recno > 1 && recno % 20 == 0) { close(file); count++;}
                 if (recno % 20 == 0) { file = "row" count ".xml" }
                 print $0 > file
                 recno++
             }' file.xml

第一个文件是row.xml。后续文件为row1.xml等。

我在这样的文件上测试了这个:

<mono> <tonous val=001/> </mono>
ignore
<mono> <tonous val=002/> </mono>
<mono> <tonous val=003/> </mono>
<mono> <tonous val=004/> </mono>
<mono> <tonous val=005/> </mono>
ignore
<mono> <tonous val=006/> </mono>
<mono> <tonous val=007/> </mono>
<mono> <tonous val=008/> </mono>
<mono> <tonous val=009/> </mono>
ignore
<mono> <tonous val=010/> </mono>
<mono> <tonous val=011/> </mono>
<mono> <tonous val=012/> </mono>
<mono> <tonous val=013/> </mono>
<mono> <tonous val=014/> </mono>
ignore
<mono> <tonous val=015/> </mono>
<mono> <tonous val=016/> </mono>
<mono> <tonous val=017/> </mono>
<mono> <tonous val=018/> </mono>
<mono> <tonous val=019/> </mono>
ignore
<mono> <tonous val=020/> </mono>
<mono> <tonous val=021/> </mono>
<mono> <tonous val=022/> </mono>
<mono> <tonous val=023/> </mono>
ignore
<mono> <tonous val=024/> </mono>
...

它包含100条<mono>行和一些ignore行(有些重复)。它生成了文件row.xmlrow1.xml,... row4.xml,每行包含20行。这是在MacOS X 10.6.6上使用标准(BSD)awk测试的。

答案 1 :(得分:1)

我会说保留“计数”变量,您只需要更改构建文件名的方式:f="row" int(count/20) ".xml"

您不必显式关闭该文件。当awk退出时,所有打开的文件都将被关闭。鉴于评论,我会发表评论。请注意,在下面的代码中,文件最多关闭20次,但会根据需要重新打开。

awk '
  /<mono/ {close f; count++; f = "row" int(count/20) ".xml"} 
  count {print >> f}
' file.xml