Comment diviser un fichier en parties égales, sans rupture de lignes individuelles? [dupliquer]

cette question a déjà une réponse ici:

je me demandais s'il était possible de diviser un fichier en parties égales ( edit: = toutes égales sauf dernier), sans rupture de la chaîne? En utilisant la commande split dans Unix, les lignes peuvent être brisées en deux. Est-il un moyen, par exemple, diviser un fichier en 5 parties égales, mais il a encore seulement constitués de l'ensemble des lignes (il n'est pas un problème si l'un des fichiers est un peu plus grand ou plus petit)? Je sais que je pourrais juste calculer le nombre de lignes, mais je dois le faire pour beaucoup de fichiers dans un script bash. Merci beaucoup!

94
demandé sur kenorb 2011-10-14 12:05:34

6 réponses

si vous voulez dire un nombre égal de lignes, split a une option pour ceci:

split --lines=75

si vous avez besoin de savoir ce que 75 devrait vraiment être pour N parties égales, its:

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

où le total des lignes peut être obtenu avec wc -l .

voir le script suivant pour un exemple:

#!/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.*

Ce sorties:

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

les versions plus récentes de split vous permettent de spécifier un nombre de CHUNKS avec l'option -n/--number . Vous pouvez donc utiliser quelque chose comme:

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

(c'est-à-dire ell-slash-six , qui signifie lines , et non one-slash-six ).

qui vous donnera des fichiers à peu près égaux en termes de taille, sans fentes de ligne médiane.

je mentionne ce dernier point parce qu'il ne vous donne pas à peu près le même nombre de lignes dans chaque fichier, plus le même nombre de caractères.

donc, si vous avez une ligne de 20 caractères et 19 lignes de 1 caractère (vingt lignes au total) et divisé en cinq fichiers, vous très probablement ne pas obtenir quatre lignes dans chaque fichier.

129
répondu paxdiablo 2015-05-30 13:02:23

le script n'est même pas nécessaire, split (1) prend en charge le trait voulu hors de la boîte:

split -l 75 auth.log auth.log. La commande ci-dessus divise le fichier en morceaux de 75 lignes par pièce, et produit le fichier sur la forme: auth.log.aa, auth.log.ab, ...

wc -l sur le fichier original et de sortie donne:

  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
36
répondu jbr 2013-04-09 09:56:24
La division

a été mise à jour dans la version 8.8 de coreutils (annoncée le 22 décembre 2010) avec l'option --number pour générer un nombre spécifique de fichiers. L'option --number=l/n génère n fichiers sans séparer les lignes.

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

19
répondu user3769065 2014-07-14 19:26:43

une solution simple pour une question simple:

split -n l/5 your_file.txt

pas besoin de script ici.

De la homme fichier", 151920920"

l/N     split into N files without splitting lines
11
répondu Kuf 2017-08-16 03:54:40

j'ai fait un script bash, qui a donné un certain nombre de parties comme entrée, a divisé un fichier

#!/bin/sh

parts_total="";
input="";

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*

j'ai utilisé head et tail commandes, et stocker dans les fichiers tmp, pour diviser les fichiers

#10 means 10 parts
sh mysplitXparts.sh input_file 10

ou avec awk, où 0,1 est 10% => 10 parties, ou 0,334 est 3 parties

awk -v size=$(wc -l < input) -v perc=0.1 '{
  nfile = int(NR/(size*perc)); 
  if(nfile >= 1/perc){
    nfile--;
  } 
  print > "split_"nfile
}' input
4
répondu Jose Ricardo Bustos M. 2015-05-11 16:36:17
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="to=xxx@gmail.com=yyy@yahoo.co.in";
string[] tokens = line.Split(new char[] { '=' }, 2, 0);

ans:
tokens[0]=to
token[1]=xxx@gmail.com=yyy@yahoo.co.in"
1
répondu Prabu 2014-10-20 12:08:19