使用 awk 每 10,000 行拆分文本文件

Sne*_*bat 7 awk

我有一个很大的 gzip 文本文件。我想要类似的东西:

zcat BIGFILE.GZ | \
    awk (snag 10,000 lines and redirect to...) | \
    gzip -9 smallerPartFile.gz
Run Code Online (Sandbox Code Playgroud)

那里的 awk 部分,我基本上希望它占用 10,000 行并将其发送到 gzip,然后重复直到原始输入文件中的所有行都被消耗掉。我找到了一个声称这样做的脚本,但是当我在我的文件上运行它然后将原始文件与拆分然后合并的文件进行比较时,缺少行。所以,awk 部分出了点问题,我不确定哪个部分坏了。

目标:

  • 对整个操作一次通读源文件
  • 将源分成更小的部分,以换行符分隔。比如说,每个文件 10,000 行
  • 压缩由于拆分操作而创建的目标文件,并且在此脚本处理后无需额外步骤即可执行此操作。

这是代码。有人可以告诉我为什么这不会产生可以拆分和合并然后成功地与原始文件进行差异的文件吗?

# Generate files part0.dat.gz, part1.dat.gz, etc.
# restore with: zcat foo* | gzip -9 > restoredFoo.sql.gz (or something like that)
prefix="foo"
count=0
suffix=".sql"

lines=10000 # Split every 10000 line.

zcat /home/foo/foo.sql.gz |
while true; do
  partname=${prefix}${count}${suffix}

  # Use awk to read the required number of lines from the input stream.
  awk -v lines=${lines} 'NR <= lines {print} NR == lines {exit}' >${partname}

  if [[ -s ${partname} ]]; then
    # Compress this part file.
    gzip -9 ${partname}
    (( ++count ))
  else
    # Last file generated is empty, delete it.
    rm -f ${partname}
    break
  fi
done
Run Code Online (Sandbox Code Playgroud)

Tho*_*hor 5

我建议在里面做所有的内务管理awk,这适用于 GNU awk:

BEGIN { file = "1" }

{ print | "gzip -9 > " file ".gz" }

NR % 10000 == 0 {
  close("gzip -9 > " file ".gz")
  file = file + 1
}
Run Code Online (Sandbox Code Playgroud)

这将保存 10000 行到1.gz,接下来的 10000 行到2.gz,等等。sprintf如果您希望在文件名生成方面具有更大的灵活性,请使用。

通过测试更新

使用的测试数据是高达 300k 的素数,可在此处找到。

wc -lc primes; md5sum primes
Run Code Online (Sandbox Code Playgroud)

输出:

25997 196958 primes
547d527ec50c2799fa6ce96dba3c26c0  primes
Run Code Online (Sandbox Code Playgroud)

现在,如果上面的 awk 程序被保存split.awk并像这样运行(使用 GNU awk):

awk -f split.awk primes
Run Code Online (Sandbox Code Playgroud)

生成三个文件(1.gz、2.gz 和 3.gz)。测试这些文件:

for f in {1..3}; do gzip -dc $f.gz >> foo; done
Run Code Online (Sandbox Code Playgroud)

测试:

diff source.file foo
Run Code Online (Sandbox Code Playgroud)

如果文件相同,输出应该是空的。

和上面相同的测试:

gzip -dc [1-3].gz | tee >(wc -lc) >(md5sum) > /dev/null
Run Code Online (Sandbox Code Playgroud)

输出:

25997  196958
547d527ec50c2799fa6ce96dba3c26c0  -
Run Code Online (Sandbox Code Playgroud)

这表明内容相同并且文件按预期拆分。