如何将一个文本文件拆分为多个文本文件

如何将一个文本文件拆分为多个文本文件

我有一个名为的文本文件entry.txt,其中包含以下内容:

[ entry1 ]
1239 1240 1242 1391 1392 1394 1486 1487 1489 1600
1601 1603 1657 1658 1660 2075 2076 2078 2322 2323
2325 2740 2741 2743 3082 3083 3085 3291 3292 3294
3481 3482 3484 3633 3634 3636 3690 3691 3693 3766
3767 3769 4526 4527 4529 4583 4584 4586 4773 4774
4776 5153 5154 5156 5628 5629 5631
[ entry2 ]
1239 1240 1242 1391 1392 1394 1486 1487 1489 1600
1601 1603 1657 1658 1660 2075 2076 2078 2322 2323
2325 2740 2741 2743 3082 3083 3085 3291 3292 3294
3481 3482 3484 3690 3691 3693 3766 3767 3769 4526
4527 4529 4583 4584 4586 4773 4774 4776 5153 5154
5156 5628 5629 5631
[ entry3 ]
1239 1240 1242 1391 1392 1394 1486 1487 1489 1600
1601 1603 1657 1658 1660 2075 2076 2078 2322 2323
2325 2740 2741 2743 3082 3083 3085 3291 3292 3294
3481 3482 3484 3690 3691 3693 3766 3767 3769 4241
4242 4244 4526 4527 4529 4583 4584 4586 4773 4774
4776 5153 5154 5156 5495 5496 5498 5628 5629 5631

我想将其拆分成三个文本文件:、、entry1.txt。其内容如下。entry2.txtentry3.txt

条目1.txt

[ entry1 ]
1239 1240 1242 1391 1392 1394 1486 1487 1489 1600
1601 1603 1657 1658 1660 2075 2076 2078 2322 2323
2325 2740 2741 2743 3082 3083 3085 3291 3292 3294
3481 3482 3484 3633 3634 3636 3690 3691 3693 3766
3767 3769 4526 4527 4529 4583 4584 4586 4773 4774
4776 5153 5154 5156 5628 5629 5631

条目2.txt

[ entry2 ]
1239 1240 1242 1391 1392 1394 1486 1487 1489 1600
1601 1603 1657 1658 1660 2075 2076 2078 2322 2323
2325 2740 2741 2743 3082 3083 3085 3291 3292 3294
3481 3482 3484 3690 3691 3693 3766 3767 3769 4526
4527 4529 4583 4584 4586 4773 4774 4776 5153 5154
5156 5628 5629 5631

条目3.txt

[ entry3 ]
1239 1240 1242 1391 1392 1394 1486 1487 1489 1600
1601 1603 1657 1658 1660 2075 2076 2078 2322 2323
2325 2740 2741 2743 3082 3083 3085 3291 3292 3294
3481 3482 3484 3690 3691 3693 3766 3767 3769 4241
4242 4244 4526 4527 4529 4583 4584 4586 4773 4774
4776 5153 5154 5156 5495 5496 5498 5628 5629 5631

换句话说,该[字符表示应该开始一个新文件。

有什么方法可以实现自动文本文件分割?我最终的实际输入entry.txt实际上包含 200,001 个条目。

在 Windows 或 Linux 中进行文本拆分会很棒。我没有 Mac 机器。谢谢!

答案1

下面是一个简单、漂亮的 gawk 单行代码:

$ gawk '{if(match($0, /^\[ (.+?) \]/, k)){name=k[1]}} {print >name".txt" }' entry.txt

这将适用于任何文件大小,与每个条目的行数无关,只要每个条目标题看起来像[ blahblah blah blah ]。请注意开头之后[和结尾之前的空格]


解释:

awkgawk逐行读取输入文件。读取每行时,其内容都会保存在变量中$0。在这里,我们告诉 awk 匹配方括号内的任何内容,并将其匹配项保存到数组中k

因此,每次匹配该正则表达式时,即对于文件中的每个标题,k[1] 都会具有行的匹配区域。即“entry1”、“entry2”或“entry3”或“entryN”。name=k[1]只需将 k[1] 的值(匹配项)保存到新变量中name

最后我们将每一行打印到一个名为的文件中<whatever value k currently has>.txt,即entry1.txt,entry2.txt......entryN.txt。

这种方法将很多对于较大的文件,它比 perl 速度更快。

我不能保证这一点,因为我从未使用过 Windows Shell,但我愿意打赌它会远的也比那更快。Gawk/awk 很快。

答案2

对于 Windows 解决方案,请尝试以下 PowerShell 脚本:

$Path = "D:\Scripts\PS\test"
$InputFile = (Join-Path $Path "log.txt")
$Reader = New-Object System.IO.StreamReader($InputFile)

While (($Line = $Reader.ReadLine()) -ne $null) {
    If ($Line -match "\[ (.+?) \]") {
        $OutputFile = $matches[1] + ".txt"
    }

    Add-Content (Join-Path $Path $OutputFile) $Line
}

相应地编辑$Path$InputFile变量。经过一些小的修改,它也可以接受该信息作为命令行参数,或者您可以将其转换为函数。

答案3

还有另一种awk解决方案:

BEGIN { 
  RS="\\[ entry[0-9]+ \\]\n"  # Record separator
  ORS=""                      # Reduce whitespace on output
}
NR == 1 { f=RT }              # Entries are of-by-one relative to matched RS
NR  > 1 {
  split(f, a, " ")            # Assuming entries do not have spaces 
  print f  > a[2] ".txt"      # a[2] now holds the bare entry name
  print   >> a[2] ".txt"
  f = RT                      # Remember next entry name
}

答案4

使用现有的命令不是更简单吗?并非所有事情都需要新的程序。

csplit /\[/ 文件

相关内容