Comment diviser un gros fichier texte en petits fichiers avec le même nombre de lignes?
j'ai un gros fichier texte (par nombre de lignes) que j'aimerais partager en petits fichiers, aussi par nombre de lignes. Donc, si mon fichier a environ 2m de lignes, je voudrais le diviser en 10 fichiers qui contiennent 200k de lignes, ou 100 fichiers qui contiennent 20k de lignes (plus un fichier avec le reste; être également divisible n'a pas d'importance).
je pourrais le faire assez facilement en Python mais je me demande s'il n'y a pas un moyen ninja de le faire en utilisant bash et unix utils (par opposition aux lignes de bouclage et de comptage / partitionnement à la main).
10 réponses
avez-vous regardé le split command?
$ split --help
Usage: split [OPTION] [INPUT [PREFIX]]
Output fixed-size pieces of INPUT to PREFIXaa, PREFIXab, ...; default
size is 1000 lines, and default PREFIX is `x'. With no INPUT, or when INPUT
is -, read standard input.
Mandatory arguments to long options are mandatory for short options too.
-a, --suffix-length=N use suffixes of length N (default 2)
-b, --bytes=SIZE put SIZE bytes per output file
-C, --line-bytes=SIZE put at most SIZE bytes of lines per output file
-d, --numeric-suffixes use numeric suffixes instead of alphabetic
-l, --lines=NUMBER put NUMBER lines per output file
--verbose print a diagnostic to standard error just
before each output file is opened
--help display this help and exit
--version output version information and exit
Vous pourriez faire quelque chose comme ceci:
split -l 200000 filename
qui va créer des fichiers chacun avec 200000 lignes nommées xaa xab xac
...
une autre option, divisée par la taille du fichier de sortie (divise encore sur les pauses de ligne):
split -C 20m --numeric-suffixes input_filename output_prefix
crée des fichiers comme output_prefix01 output_prefix02 output_prefix03 ...
de taille max 20 mégaoctets chacun.
Oui, il y a une commande split
. Il divisera un fichier en lignes ou en octets.
$ split --help
Usage: split [OPTION]... [INPUT [PREFIX]]
Output fixed-size pieces of INPUT to PREFIXaa, PREFIXab, ...; default
size is 1000 lines, and default PREFIX is `x'. With no INPUT, or when INPUT
is -, read standard input.
Mandatory arguments to long options are mandatory for short options too.
-a, --suffix-length=N use suffixes of length N (default 2)
-b, --bytes=SIZE put SIZE bytes per output file
-C, --line-bytes=SIZE put at most SIZE bytes of lines per output file
-d, --numeric-suffixes use numeric suffixes instead of alphabetic
-l, --lines=NUMBER put NUMBER lines per output file
--verbose print a diagnostic just before each
output file is opened
--help display this help and exit
--version output version information and exit
SIZE may have a multiplier suffix:
b 512, kB 1000, K 1024, MB 1000*1000, M 1024*1024,
GB 1000*1000*1000, G 1024*1024*1024, and so on for T, P, E, Z, Y.
utiliser split
divise un fichier en morceaux de taille fixe, crée des fichiers de sortie contenant des sections consécutives D'entrée (entrée standard si aucune n'est donnée ou entrée est` -')
Syntax
split [options] [INPUT [PREFIX]]
utiliser:
sed -n '1,100p' filename > output.txt
ici, 1 et 100 sont les numéros de ligne que vous allez capturer dans output.txt
.
vous pouvez également utiliser awk
awk -vc=1 'NR%200000==0{++c}{print "151900920" > c".txt"}' largefile
diviser le fichier "fichier.txt "dans les fichiers de 10000 lignes:
split -l 10000 file.txt
dans le cas où vous voulez simplement diviser par x le nombre de lignes de chaque dossier, les asnwers donnés environ split
sont OK. Mais, je suis curieux de voir que personne n'a prêté attention aux exigences:
- "sans devoir les Compter" - > en utilisant wc + coupe
- "avoir le reste dans des fichiers" -> split n'par défaut
je ne peux pas le faire sans "wc + coupe", mais je suis sur que:
split -l $(expr `wc $filename | cut -d ' ' -f3` / $chunks) $filename
cela peut être facilement ajouté à vos fonctions bashrc de sorte que vous pouvez simplement l'invoquer en passant le nom du fichier et des morceaux:
split -l $(expr `wc | cut -d ' ' -f3` / )
dans le cas où vous voulez juste x morceaux sans reste dans le fichier supplémentaire, il suffit d'adapter la formule pour la somme (Morceaux - 1) sur chaque fichier. J'utilise cette approche parce que d'habitude je veux juste x nombre de fichiers plutôt que x lignes par fichier:
split -l $(expr `wc | cut -d ' ' -f3` / + `expr - 1`)
vous pouvez ajouter cela à un script et l'appeler votre "voie ninja", parce que si rien ne correspond à vos besoins, vous pouvez le construire: -)
split
(tiré de GNU coreutils, depuis version 8.8 de 2010-12-22 ) inclut le paramètre suivant:
-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/records
l/K/N output Kth of N to stdout without splitting lines/records
r/N like 'l' but use round robin distribution
r/K/N likewise but only output Kth of N to stdout
ainsi, split -n 4 input output.
générera quatre fichiers ( output.a{a,b,c,d}
) avec le même nombre d'octets, mais les lignes peuvent être brisées au milieu.
si nous voulons préserver les lignes complètes (c'est-à-dire séparées par des lignes), alors cela devrait fonctionner:
split -n l/4 input output.
réponse connexe: https://stackoverflow.com/a/19031247
HDFS getmerge fichier de petite taille et versé dans la taille de la propriété.
cette méthode causera un bris de ligne
split-B 125m compact.fichier -d-3 compact_prefix
j'ai essayé de getmerge et divisé en environ 128MB chaque dossier.
divisé en 128m ,le juge sizeunit est M ou G ,s'il vous plaît tester avant utilisation.
begainsize=`hdfs dfs -du -s -h /externaldata/$table_name/$date/ | awk '{ print }' `
sizeunit=`hdfs dfs -du -s -h /externaldata/$table_name/$date/ | awk '{ print }' `
if [ $sizeunit = "G" ];then
res=$(printf "%.f" `echo "scale=5;$begainsize*8 "|bc`)
else
res=$(printf "%.f" `echo "scale=5;$begainsize/128 "|bc`) # celling ref http://blog.csdn.net/naiveloafer/article/details/8783518
fi
echo $res
# split into $res files with number suffix. ref http://blog.csdn.net/microzone/article/details/52839598
compact_file_name=$compact_file"_"
echo "compact_file_name :"$compact_file_name
split -n l/$res $basedir/$compact_file -d -a 3 $basedir/${compact_file_name}