web-dev-qa-db-fra.com

Comment diviser un fichier texte volumineux en fichiers plus petits avec un nombre égal de lignes?

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).

410
danben

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.

712
Mark Byers

Qu'en est-il de la commande split ?

split -l 200000 mybigfile.txt
69
Robert Christie

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.
34
Dave Kirby

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]]

http://ss64.com/bash/split.html

13
zmbush

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.

12
Harshwardhan

scinder le fichier "fichier.txt" en 10000 lignes:

split -l 10000 file.txt
9
ialqwaiz

vous pouvez aussi utiliser awk

awk -vc=1 'NR%200000==0{++c}{print $0 > c".txt"}' largefile
8
ghostdog74

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:

  • "sans avoir à les compter" -> en utilisant wc + cut
  • "avoir le reste dans un fichier supplémentaire" -> split fait par défaut

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 :-)

6
erm3nda

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

4

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}
0
Matiji66