J'ai un fichier texte brut volumineux (par nombre de lignes) que je voudrais scinder en fichiers plus petits, également par nombre de lignes. Donc, si mon fichier contient environ 2 millions de lignes, j'aimerais le scinder en 10 fichiers contenant 200 000 lignes, ou 100 fichiers contenant 20 000 lignes (plus un fichier avec le reste; le fait d'être divisible de manière égale n'a pas d'importance).
Je pourrais le faire assez facilement en Python, mais je me demande s’il existe un moyen de le faire en utilisant des utilitaires bash et unix (au lieu de boucler manuellement et de compter/partitionner des lignes).
Avez-vous regardé la commande split?
$ 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 pouvez faire quelque chose comme ça:
split -l 200000 filename
qui créera des fichiers de 200 000 lignes chacune nommée xaa xab xac
...
Une autre option, divisée par la taille du fichier de sortie (toujours divisée sur les sauts de ligne):
split -C 20m --numeric-suffixes input_filename output_prefix
crée des fichiers comme output_prefix01 output_prefix02 output_prefix03 ...
chacun d’une taille maximale de 20 mégaoctets.
Qu'en est-il de la commande split ?
split -l 200000 mybigfile.txt
Oui, il existe 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
Fractionner un fichier en parties de taille fixe, créer des fichiers de sortie contenant des sections consécutives de INPUT (entrée standard si aucune donnée n'est fournie ou si INPUT est `- ')
Syntax
split [options] [INPUT [PREFIX]]
Utilisation:
sed -n '1,100p' filename > output.txt
Ici, 1 et 100 sont les numéros de ligne que vous allez capturer dans output.txt
.
scinder le fichier "fichier.txt" en 10000 lignes:
split -l 10000 file.txt
vous pouvez aussi utiliser awk
awk -vc=1 'NR%200000==0{++c}{print $0 > c".txt"}' largefile
Si vous voulez simplement diviser chaque fichier par x nombre de lignes, les réponses données à propos de split
sont correctes. Mais je suis curieux de savoir que personne ne fait attention aux exigences:
Je ne peux pas faire ça sans "wc + cut", mais j'utilise ça:
split -l $(expr `wc $filename | cut -d ' ' -f3` / $chunks) $filename
Ceci peut être facilement ajouté à vos fonctions bashrc afin que vous puissiez simplement l'invoquer en passant le nom de fichier et les morceaux:
split -l $(expr `wc $1 | cut -d ' ' -f3` / $2) $1
Si vous voulez seulement x morceaux sans reste dans un fichier supplémentaire, adaptez simplement la formule pour la résumer (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 $1 | cut -d ' ' -f3` / $2 + `expr $2 - 1`) $1
Vous pouvez ajouter cela à un script et l'appeler votre "manière ninja", car si rien ne répond à vos besoins, vous pouvez le construire :-)
split
(de GNU coreutils, depuis version 8.8 du 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 pourraient être interrompues au milieu.
Si nous voulons conserver des lignes complètes (c'est-à-dire divisées par lignes), alors cela devrait fonctionner:
split -n l/4 input output.
Réponse associée: https://stackoverflow.com/a/19031247
HDFS getmerge petit fichier et débordé dans la taille de la propriété.
Cette méthode provoquera un saut de ligne
split -b 125m compact.file -d -a 3 compact_prefix
J'essaie d'obtenir et de diviser en environ 128 Mo chaque fichier.
# split into 128m ,judge sizeunit is M or G ,please test before use.
begainsize=`hdfs dfs -du -s -h /externaldata/$table_name/$date/ | awk '{ print $1}' `
sizeunit=`hdfs dfs -du -s -h /externaldata/$table_name/$date/ | awk '{ print $2}' `
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}