我有一个基于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
答案 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