Je me demandais s'il était possible de diviser un fichier en parties égales ( éditer : \= tous égaux sauf le dernier), sans casser la ligne ? En utilisant la commande split d'Unix, les lignes peuvent être coupées en deux. Existe-t-il un moyen de diviser un fichier en 5 parties égales, par exemple, tout en ne conservant que des lignes entières (ce n'est pas un problème si l'un des fichiers est un peu plus grand ou plus petit) ? Je sais que je pourrais simplement calculer le nombre de lignes, mais je dois le faire pour un grand nombre de fichiers dans un bash script. Merci beaucoup !
Réponses
Trop de publicités?Si vous voulez dire un nombre égal de lignes, split
a une option pour cela :
split --lines=75
Si vous avez besoin de savoir ce que 75
devrait vraiment être pour N
à parts égales, son :
lines_per_part = int(total_lines + N - 1) / N
où les lignes totales peuvent être obtenues 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.*
Ces 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
Des versions plus récentes de split
vous permettent de spécifier un nombre de CHUNKS
avec le -n/--number
option. Vous pouvez donc utiliser quelque chose comme :
split --number=l/6 ${fspec} xyzzy.
(c'est ell-slash-six
c'est-à-dire lines
pas one-slash-six
).
Vous obtiendrez ainsi des fichiers de taille à peu près égale, sans que la ligne médiane ne soit divisée.
Je mentionne ce dernier point parce que cela ne vous donne pas à peu près le même nombre de lignes dans chaque fichier, plus le même nombre de des personnages.
Ainsi, si vous avez une ligne de 20 caractères et 19 lignes de 1 caractère (vingt lignes au total) et que vous les avez divisées en cinq fichiers, il est probable que ne le fera pas obtenir quatre lignes dans chaque fichier.
Le script n'est même pas nécessaire, split(1) prend en charge la fonctionnalité souhaitée dès le départ :split -l 75 auth.log auth.log.
La commande ci-dessus divise le fichier en morceaux de 75 lignes chacun, et sort le fichier sur le formulaire : auth.log.aa, auth.log.ab, ...
wc -l
sur le fichier original et la 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
Une solution simple pour une question simple :
split -n l/5 your_file.txt
pas besoin de script ici.
De la homme fichier, CHUNKS may be:
l/N split into N files without splitting lines
Mise à jour
Toutes les distributions Unix n'incluent pas ce drapeau. Par exemple, il ne fonctionnera pas sous OSX. Pour l'utiliser, vous pouvez considérer remplacer les utilitaires de Mac OS X par des utilitaires de base GNU .
Split a été mis à 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 diviser 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
J'ai fait un bash script, qui étant donné un nombre de parties comme entrée, divise un fichier
#!/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*
J'ai utilisé head
et tail
et stocker dans des 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
- Réponses précédentes
- Plus de réponses