Bash:在linux中,仅通过空行将文件拆分为10个部分
我目前正在使用Scala应用程序解析一些文件。问题是文件太大,所以它们总是在堆大小中抛出异常(我尝试了最大堆大小,但仍然没有用) 现在,文件如下所示:Bash:在linux中,仅通过空行将文件拆分为10个部分,linux,bash,file,scala,split,Linux,Bash,File,Scala,Split,我目前正在使用Scala应用程序解析一些文件。问题是文件太大,所以它们总是在堆大小中抛出异常(我尝试了最大堆大小,但仍然没有用) 现在,文件如下所示: This is one paragraph for Scala to parse This is another paragraph for Scala to parse Yet another paragraph 等等。基本上,我想把所有这些文件分成10或20个部分,但我必须确保一个段落不会在结果中一分为二。有没有办法做到这一点 谢谢大家
This is
one paragraph
for Scala
to parse
This is
another paragraph
for Scala
to parse
Yet another
paragraph
等等。基本上,我想把所有这些文件分成10或20个部分,但我必须确保一个段落不会在结果中一分为二。有没有办法做到这一点
谢谢大家! 您可以使用“拆分”命令,但当您想要拆分段落时,可以使用这种脚本:
awk -v RS="\n\n" 'BEGIN {n=1}{print $0 > "file"n++".txt"}' yourfile.txt
在名为“file1.txt”、“file2.txt”的文件中拆分每个段落
要为每个“n”段落设置“n++”,可以执行以下操作:
awk -v RS="\n\n" 'BEGIN{n=1; i=0; nbp=100}{if (i++ == nbp) {i=0; n++} print $0 > "file"n".txt"}' yourfile.txt
只需更改“nbp”值即可设置段落编号,以便每3个段落拆分一次:
awk 'BEGIN{nParMax=3;npar=0;nFile=0}
/^$/{npar++;if(npar==nParMax){nFile++;npar=0;next}}
{print $0 > "foo."nFile}' foo.orig
要每10行拆分一次,请执行以下操作:
awk 'BEGIN{nLineMax=10;nline=0;nFile=0}
/^$/{if(nline>=nLineMax){nFile++;nline=0;next}}
{nline++;print $0 > "foo."nFile}' foo.orig
下面是一个awk脚本,它将把输入文件分解成
batch\u size
块(用垃圾跟踪记录分隔换行符)。将其放入文件并将其更改为可执行文件:
#!/usr/bin/awk -f
BEGIN {RS=""; ORS="\n\n"; last_f=""; batch_size=20}
# perform setup whenever the filename changes
FILENAME!=last_f {r_per_f=calc_r_per_f(); incr_out(); last_f=FILENAME; fnum=1}
# write a record to an output file
{print $0 > out}
# after a batch, change the file name
(FNR%r_per_f)==0 {incr_out()}
# function to roll the file name
function incr_out() {close(out); fnum++; out=FILENAME"_"fnum".out"}
# function to get the number of records per file
function calc_r_per_f() {
cmd=sprintf( "grep \"^$\" %s | wc -l", FILENAME )
cmd | getline rcnt
close(cmd)
return( sprintf( "%d", rcnt/batch_size ) )
}
您可以更改begin块中的batch\u size
元素,以调整每个输入文件的输出文件数,并且可以通过在incr\u out()
中更改out=
赋值来更改输出文件名本身
如果您将它放入一个名为
awko
的文件中,您将像awko data1 data2
那样运行它,并获得像data2\u 7.out
这样的文件。当然,如果您的输入文件名具有扩展名等,则输出名称比输入文件名更可怕。csplit file.txt/^$/{*}
csplit
分割由指定图案分隔的文件
/^$/
匹配空行
{*}
无限期地重复前面的模式。要将包含X个段落的文件拆分为n个(10
以下)文件,其中X是大于或等于n的数字,则为:
awk -v RS= -v ORS='\n\n' -n 10 '
NR==FNR { totParas=NR; parasPerFile=2; next }
(FNR % parasPerFile) == 1 {
close(out)
out = FILENAME "_out" (++c)
parasLeft = totParas - (FNR - 1)
parasPerFile = int(parasLeft/n) + (parasLeft%n ? 1 : 0)
}
{ print > out }
' file file
看这个:那对我没用:/I我已经做了。尽管如此,我必须在应用程序中保存所有解析的段落,拥有较小的文件比更改所有程序逻辑更简单(加上我没有太多时间来做)。问题被标记为bash:那么将其拆分到单独的Scala程序中如何?我最终用一个懒惰的迭代器解决了Brian所说的问题。必须更改程序的一些逻辑,但没有我原来想象的那么多。这种方式的问题是段落可能会变得太多(一个文件可以容纳超过10万个段落,而文件超过50个):/您可以更新每n个段落的“n”,我可以编辑我的命令来设置它。
csplit
允许您按模式而不是大小进行分割。要实现我们(我,fredtantini…)在评论中的目的非常复杂。那完全一样。。。不是吗对不起,我刚刚了解到,您允许拆分为“n”个文件,因为我们在解决方案中设置了“n”个段落。这并不复杂(只有3个动作),实际上是类似的。与其他解决方案一样,它允许每个输入文件中的~n
单个文件。它的不同之处在于,它对每个文件执行操作时,输出文件与输入文件名相关,每个输入文件被分解为与其他文件数量大致相同的子文件(calc\u r\u per\u f()
)。当被调用时,它应该像awko data1 data2 data3 data4…
一样工作,就像awko data1
+awko data2
+。这些函数减少了复制的代码并使操作块保持较短。让我知道我是否可以改进评论。谢谢你的回答,向上投票!如果您不介意的话,使用这种模式,我99.99%的时间都能完成工作。然而,在一段时间里,我得到的“段落”随机分裂在中间的一行。知道为什么会这样吗?