awk错误“打开太多文件”

时间:2014-05-07 04:51:18

标签: regex bash shell awk

我有一个基于awk的拆分器,它根据正则表达式拆分一个巨大的文件。但问题是我得到了太多的文件错误。即使我有条件关闭。如果你能帮助我弄清楚我做错了什么,我将非常感激。

    awk 'BEGIN { system("mkdir -p splitted/sub"++j) }
    /<doc/{x="F"++i".xml";}{
     if (i%5==0 ){
       ++i;
       close("splitted/sub"j"/"x);
       system("mkdir -p splitted/sub"++j"/");
      }
     else{
       print > ("splitted/sub"j"/"x);
     }
    }' wiki_parsed.xml

2 个答案:

答案 0 :(得分:4)

简单的答案是,关闭并不经常被调用。以下是原因的说明性示例:

使用输入文件,如:

<doc somestuff
another line
yet another line
<doc the second
still more data
<doc the third
<doc the fourth
<doc the fifth

我可以根据您的脚本创建一个可执行的awk文件,如:

#!/usr/bin/awk -f

BEGIN { system_(++j) }

/<doc/{x=++i}

{
    if (i%5==0 ){ ++i; close_(j"/"x); system_(++j) }
    else{ open_(j"/"x) }
}

function call_f(funcname, arg) { print funcname"("arg")" }

function system_(cnt) { call_f( "system", cnt ) }
function open_(f) { if( !(f in a) ) { call_f( "open", f ); a[f]++ } }
function close_(f) { call_f( "close", f ) }

如果我放入名为awko的文件,则可以像awko data一样运行以生成以下内容:

system(1)
open(1/1)
open(1/2)
open(1/3)
open(1/4)
close(1/5)
system(2)

我制作的脚本只是通过使用尾随_的本地函数遮蔽实际函数调用来指示您调用每个函数的次数。请注意相同参数与open()相比打印close()的次数。此外,我最终将print >重命名为open_只是为了说明它打开了文件(每个文件名一次)。

如果我将可执行文件awk文件更改为以下内容,您可以看到close足够调用:

#!/usr/bin/awk -f

BEGIN { system_(++j) }

/<doc/{ close_(j"/"x); x=++i } # close_() call is moved to here.

{
    if (i%5==0 ){ ++i; system_(++j) }
    else{ open_(j"/"x) }
}

function call_f(funcname, arg) { print funcname"("arg")" }

function system_(cnt) { call_f( "system", cnt ) }
function open_(f) { if( !(f in a) ) { call_f( "open", f ); a[f]++ } }
function close_(f) { call_f( "close", f ) }

给出以下输出:

system(1)
close(1/)
open(1/1)
close(1/1)
open(1/2)
close(1/2)
open(1/3)
close(1/3)
open(1/4)
close(1/4)
system(2)

应该清楚close()被召唤的时间比足够多。它第一次被调用在一个不存在的文件上。通过真正的close()调用,应该忽略从未打印过这样一个文件的事实,并且不会尝试实际关闭。在其他情况下,最后open()close()电话匹配。

如第二个示例脚本中那样在脚本中移动close()调用应修复错误。

答案 1 :(得分:1)

这就是我让它完美运作

    awk 'BEGIN { system("mkdir -p splitted/sub"++j) }
     /<doc/{x="F"++i".xml";}{

      if (i%1995==0 ){
       ++i;
       system("mkdir -p splitted/sub"++j"/");
      }
      else{
       print >> ("splitted/sub"j"/"x);
       close("splitted/sub"j"/"x);
      }

     }' wiki_parsed.xml