【问题标题】:How do I split a file into n no of parts如何将文件拆分为 n 个部分
【发布时间】:2011-03-12 18:46:28
【问题描述】:

我有一个文件不连续。我想将文件拆分为具有特定名称的 n 个文件。每个文件中有多少行并不重要。我只想要特定的文件数(比如 5 个)。这里的问题是原始文件中的行数不断变化。所以我需要计算行数,然后将文件分成 5 个部分。如果可能,我们必须将它们分别发送到不同的目录中。

【问题讨论】:

  • 用什么?一个工具,一种编程语言,一个脚本……?
  • Windows、Linux?您可以使用哪些语言?

标签: file split


【解决方案1】:

在 macOS 上,您可以简单地这样做:

split -n <number_of_parts> <filename>

例如,你可以这样做

split -n 5 file.txt

它将被分成5个行数相似的文件。

【讨论】:

    【解决方案2】:

    这是一个带变量的单行器

    file=onepiece.log; nsplit=5; len=$(wc -l < $file); split -l$(($len/$nsplit)) "$file" "$file.split" -da 4
    

    【讨论】:

      【解决方案3】:

      split 有一个选项“--number=CHUNKS”,可让您将文件分成多个块。 这是来自“split --help”的(修剪过的)输出:

        -n, --number=CHUNKS     generate CHUNKS output files; see explanation below
      
      ...
      
      CHUNKS may be:
      N       split into N files based on size of input
      K/N     output Kth of N to stdout
      l/N     split into N files without splitting lines
      l/K/N   output Kth of N to stdout without splitting lines
      r/N     like 'l' but use round robin distribution
      r/K/N   likewise but only output Kth of N to stdout
      

      如果将其拆分为 5 个部分,则命令为: split --number=l/5 inputfile outputprefix

      不过,这可能不会导致它们具有相同的行数。

      如果您希望它们在最后一行之前都具有相同的行数,您可以使用以下命令: split -l $(( ($(cat "inputfile" | wc -l) + 5 - 1)/5 )) inputfile outputprefix 这里的两个 5 都可以替换为任何其他数字(确保它们相同)。

      以下是对该命令的逐条解释:

      $( ) 返回您输入的任何命令的输出。 cat 在这里用于确保 wc 只返回行数而不输出输入文件名。

      $(( )) 将括号内的内容作为数学表达式(仅使用整数)求值并返回结果。

      ($(cat "inputfile" | wc -l) + 5 - 1)/5 获取输入文件的行数并加 5,减 1,然后将结果除以 5。除法前的加法和减法确保结果四舍五入,以便准确给出部分数你想要(在这种情况下是 5 个)。

      您还可以使用split --number=r/5 将其拆分为四个文件,其中每一行分布在它们之间,如下例所示:

      inputfile.txt:
      1
      2
      3
      4
      5
      6
      7
      8
      9
      
      outputfile1:
      1
      6
      
      outputfile2:
      2
      7
      
      outputfile3:
      3
      8
      
      outputfile4:
      4
      9
      
      outputfile5:
      5
      

      这不会保留文件顺序。但在不重要的情况下它可能很有用。

      【讨论】:

      • stackoverflow.com/a/45704863/394585 的评论中添加清晰度。请注意,number=l/5 的分子中有字母 l,而不是数字 1。它难住了我。
      • 并非所有版本的 split 都有 -r 选项
      【解决方案4】:

      这是基于@sketchytechky 和@grasshopper 给出的原始答案。如果您想以不同的方式处理余数并希望将固定数量的文件作为输出但循环分配行,那么 split 命令应编写为:

      split -da 4 -n r/1024 filename filename_split --additional-suffix=".log"。将 1024 替换为您想要作为输出的文件数。

      【讨论】:

        【解决方案5】:

        在 bash 中,您可以使用 split 命令根据所需的行数对其进行拆分。您可以使用wc 命令来确定需要多少行。这是wcsplit 合并为一行。

        例如,将onepiece.log 拆分为 5 个部分

            split -l$((`wc -l < onepiece.log`/5)) onepiece.log onepiece.split.log -da 4
        

        这将创建像onepiece.split.log0000 这样的文件...

        注意:bash 除法四舍五入,所以如果有余数,就会有第 6 部分文件。

        【讨论】:

        • split -da 4 -l $((wc -l &lt; onepiece.log/5)) onepiece.log part --additional-suffix=".log" 这将命名文件以直观的方式 - 即 part0001.log、part0002.log 等,而不是拆分的默认命名。 -da 4 表示我们想要一个长度为 4 的数字后缀。阅读“man split”以获得更多自定义选项。 PS:所以吃了 cmets 的 backtics
        • 这个答案比stackoverflow和askubuntu上的两个higher upvoted questions更简洁。
        • 为了处理余数,如果像我这样的人想要固定数量的文件作为输出但循环分配行,那么上面的命令可以修改为:split -da 4 -nr/1024 文件名 filename_split --additional-suffix=".log"。将 1024 替换为您想要作为输出的文件数。
        • @Vishnu 您应该将此作为答案而不是评论,它非常有帮助,更多的人会将其视为答案而不是评论。
        • @G.LC 我刚刚添加它作为答案。
        【解决方案6】:

        在linux上,有一个split命令,

        split --lines=1m /path/to/large/file /path/to/output/file/prefix
        

        输出固定大小的 INPUT 到 PREFIXaa, PREFIXab, ...;默认大小为 1000 行,默认 PREFIX 为“x”。没有 INPUT,或者当 INPUT 为 - 时,读取标准输入。

        ...

        -l, --lines=NUMBER 每个输出文件放 NUMBER 行

        ...

        不过,您必须事先计算分割的实际大小。

        【讨论】:

        • 这是按行还是按字节拆分?
        • 这里文件的大小也每天都在变化。所以我需要一般的答案,我们不应该使用大小或行数
        • 我必须为此编写一个 shell 脚本。有人可以帮我吗
        • sintax --lines=1m 是什么意思?
        【解决方案7】:

        我可以想出几种方法来做到这一点。您将使用哪个在很大程度上取决于数据。

        1. 行是固定长度:通过读取文件的目录条目来查找文件的大小,然后除以行长得到行数。使用它来确定每个文件有多少行。

        2. 文件只需要具有大致相同的行数。再次从目录条目中读取文件大小。读取前 N 行(N 应该很小,但文件的一些合理部分)以计算平均行长度。根据文件大小和预测的平均行长计算大概的行数。这假设线长度服从正态分布。如果没有,请调整您的方法以随机采样行(使用 seek() 或类似的东西)。取平均值后倒回文件,然后根据预测的行长将其拆分。

        3. 读取文件两次。第一次计算行数。第二次将文件拆分成必要的部分。

        编辑:使用 shell 脚本(根据您的 cmets),#2 的随机版本将很难,除非您编写一个小程序来为您执行此操作。您应该能够使用ls -l 来获取文件大小,wc -l 来计算确切的行数,并使用head -nNNN | wc -c 来计算平均行长度。

        【讨论】:

          【解决方案8】:

          假设您正在处理一个文本文件,然后 wc -l 确定总行数,split -l 拆分为指定数量的行(在您的情况下为总计 / 5)。这适用于 UNIX/Mac 和 Windows(如果您安装了 cygwin

          【讨论】:

            猜你喜欢
            • 2013-09-29
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            相关资源
            最近更新 更多