Bash:在linux中,仅通过空行将文件拆分为10个部分

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个部分,但我必须确保一个段落不会在结果中一分为二。有没有办法做到这一点 谢谢大家

我目前正在使用Scala应用程序解析一些文件。问题是文件太大,所以它们总是在堆大小中抛出异常(我尝试了最大堆大小,但仍然没有用)

现在,文件如下所示:

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%的时间都能完成工作。然而,在一段时间里,我得到的“段落”随机分裂在中间的一行。知道为什么会这样吗?