Как разбить файл на равные части, не разбивая отдельные строки?

Мне было интересно, можно ли разделить файл на равные части (edit: = all equal за исключением последнего), не нарушая строку? Используя команду split в Unix, строки могут быть разбиты пополам. Есть ли способ, скажем, разделить файл на 5 равных частей, но он все еще состоит только из целых строк (это не проблема, если один из файлов немного больше или меньше)? Я знаю, что могу просто рассчитать количество строк, но я должен сделать это для большого количества файлов в bash script. Большое спасибо!

Ответ 1

Если вы имеете в виду равное количество строк, split имеет для этого вариант:

split --lines=75

Если вам нужно знать, что этот 75 действительно должен быть для N равных частей, его:

lines_per_part = int(total_lines + N - 1) / N

где общие строки могут быть получены с помощью wc -l.

Для примера см. следующий script:

#!/usr/bin/bash

# Configuration stuff

fspec=qq.c
num_files=6

# Work out lines per file.

total_lines=$(wc -l <${fspec})
((lines_per_file = (total_lines + num_files - 1) / num_files))

# Split the actual file, maintaining lines.

split --lines=${lines_per_file} ${fspec} xyzzy.

# Debug information

echo "Total lines     = ${total_lines}"
echo "Lines  per file = ${lines_per_file}"    
wc -l xyzzy.*

Выводится:

Total lines     = 70
Lines  per file = 12
  12 xyzzy.aa
  12 xyzzy.ab
  12 xyzzy.ac
  12 xyzzy.ad
  12 xyzzy.ae
  10 xyzzy.af
  70 total

Более поздние версии split позволяют указать число CHUNKS с опцией -n/--number. Поэтому вы можете использовать что-то вроде:

split --number=l/6 ${fspec} xyzzy.

(это ell-slash-six, что означает lines, а не one-slash-six).

Это даст вам примерно равные файлы с точки зрения размера без разделителей средней строки.

Я упоминаю эту последнюю точку, потому что она не дает вам примерно одинакового количества строк в каждом файле, больше того же количества символов.

Итак, если у вас есть одна 20-символьная строка и 19 1-символьных строк (всего двадцать строк) и разделены на пять файлов, вы, скорее всего, не получите четыре строки в каждом файле.

Ответ 2

script даже не требуется, split (1) поддерживает нужную функцию из коробки:
split -l 75 auth.log auth.log. Вышеупомянутая команда разбивает файл на куски 75 строк на кусок и выводит файл в форме: auth.log.aa, auth.log.ab, ...

wc -l в исходном файле и вывод дает:

  321 auth.log
   75 auth.log.aa
   75 auth.log.ab
   75 auth.log.ac
   75 auth.log.ad
   21 auth.log.ae
  642 total

Ответ 3

Разделение

было обновлено в выпуске 8.8 coreutils (объявлено 22 декабря 2010 г.) с опцией -number для генерации определенного количества файлов. Параметр --number = l/n генерирует n файлов без разделительных линий.

http://www.gnu.org/software/coreutils/manual/html_node/split-invocation.html#split-invocation http://savannah.gnu.org/forum/forum.php?forum_id=6662

Ответ 4

Я сделал bash script, который задал несколько частей в качестве входных данных, разделил файл

#!/bin/sh

parts_total="$2";
input="$1";

parts=$((parts_total))
for i in $(seq 0 $((parts_total-2))); do
  lines=$(wc -l "$input" | cut -f 1 -d" ")
  #n is rounded, 1.3 to 2, 1.6 to 2, 1 to 1
  n=$(awk  -v lines=$lines -v parts=$parts 'BEGIN { 
    n = lines/parts;
    rounded = sprintf("%.0f", n);
    if(n>rounded){
      print rounded + 1;
    }else{
      print rounded;
    }
  }');
  head -$n "$input" > split${i}
  tail -$((lines-n)) "$input" > .tmp${i}
  input=".tmp${i}"
  parts=$((parts-1));
done
mv .tmp$((parts_total-2)) split$((parts_total-1))
rm .tmp*

Я использовал команды head и tail и сохранял в файлах tmp, чтобы разделить файлы

#10 means 10 parts
sh mysplitXparts.sh input_file 10

или с awk, где 0,1 составляет 10% = > 10 частей, или 0,334 составляет 3 части

awk -v size=$(wc -l < input) -v perc=0.1 '{
  nfile = int(NR/(size*perc)); 
  if(nfile >= 1/perc){
    nfile--;
  } 
  print > "split_"nfile
}' input

Ответ 5

Простое решение для простого вопроса:

split -n l/5 your_file.txt

нет необходимости в создании сценариев здесь.

Из файла man, CHUNKS may be:

l/N     split into N files without splitting lines

Ответ 6

var dict = File.ReadLines("test.txt")
               .Where(line => !string.IsNullOrWhitespace(line))
               .Select(line => line.Split(new char[] { '=' }, 2, 0))
               .ToDictionary(parts => parts[0], parts => parts[1]);


or 

    enter code here

line="[email protected][email protected]";
string[] tokens = line.Split(new char[] { '=' }, 2, 0);

ans:
tokens[0]=to
token[1][email protected][email protected]"