J'ai un fichier .msg assez volumineux formaté au format UIEE.
$ wc -l big_db.msg
8726593 big_db.msg
Essentiellement, le fichier est composé d'entrées de différentes longueurs qui ressemblent à ceci:
UR|1
AA|Condon, Richard
TI|Prizzi's Family
CN|Collectable- Good/Good
MT|FICTION
PU|G.P. Putnam & Sons
DP|1986
ED|First Printing.
BD|Hard Cover
NT|0399132104
KE|MAFIA
KE|FICTION
PR|44.9
XA|4
XB|1
XC|BO
XD|S
UR|10
AA|Gariepy, Henry
TI|Portraits of Perseverance
CN|Good/No Jacket
MT|SOLD
PU|Victor Books
DP|1989
BD|Mass Market Paperback
NT|1989 tpb g 100 meditations from the Book of Job "This book...help you
NT| persevere through the struggles of your life..."
KE|Bible
KE|religion
KE|Job
KE|meditations
PR|28.4
XA|4
XB|5
XC|BO
XD|S
Ceci est un exemple de deux entrées, séparées par une ligne vierge. Je souhaite diviser ce gros fichier en fichiers plus petits sans casser une entrée en deux fichiers.
Chaque entrée individuelle est séparée par une nouvelle ligne (une ligne complètement vierge) dans le fichier. Je souhaite diviser ce fichier de 8,7 millions de lignes en 15 fichiers. Je comprends que des outils comme split
existent, mais je ne sais pas trop comment diviser le fichier, mais le diviser uniquement sur une nouvelle ligne afin qu'une seule entrée ne soit pas divisée en plusieurs fichiers.
text-processing
split
user2036066
la source
la source
csplit
existe aussi.|
(commeUR
,AA
,TI
) pertinents pour le nombre de fichiers, même le même pour être exact?Réponses:
Voici une solution qui pourrait fonctionner:
Cela fonctionne en permettant au premier
sed
d'écrire lesed
script du second . La secondesed
première rassemble toutes les lignes d'entrée jusqu'à ce qu'elle rencontre une ligne vierge. Il écrit ensuite toutes les lignes de sortie dans un fichier. Le premiersed
écrit un script pour le second lui indiquant où écrire sa sortie. Dans mon cas de test, ce script ressemblait à ceci:Je l'ai testé comme ceci:
Cela m'a fourni un fichier de 6000 lignes, qui ressemblait à ceci:
... répété 1000 fois.
Après avoir exécuté le script ci-dessus:
PRODUCTION
la source
En utilisant la suggestion de
csplit
:Fractionnement basé sur les numéros de ligne
Exemple
Disons que j'ai un fichier contenant 1 000 lignes.
donne des fichiers comme ceci:
Vous pouvez contourner la limitation statique d'avoir à spécifier le nombre de répétitions en pré-calculant les nombres en fonction du nombre de lignes dans votre fichier particulier à l'avance.
Fractionnement basé sur des lignes vides
Si, par contre, vous souhaitez simplement fractionner un fichier sur des lignes vides contenues dans le fichier, vous pouvez utiliser cette version de
split
:Exemple
Supposons que j'ai ajouté 4 lignes vides à ce qui
file.txt
précède et créez le fichierfile2.txt
. Vous pouvez voir qu'ils ont été ajoutés manuellement comme suit:Ce qui précède montre que je les ai ajoutés entre les numéros correspondants dans mon exemple de fichier. Maintenant, lorsque j'exécute la
csplit
commande:Vous pouvez voir que j'ai maintenant 4 fichiers qui ont été divisés en fonction de la ligne vierge:
Références
la source
Si vous ne vous souciez pas de l'ordre des enregistrements, vous pouvez faire:
Sinon, vous devez d'abord obtenir le nombre d'enregistrements, pour savoir combien mettre dans chaque fichier de sortie:
la source
file.in
etfile.out
?Si vous cherchez à diviser uniquement à la fin d'une ligne, vous devriez pouvoir le faire avec l'
-l
option poursplit
.Si vous cherchez à diviser sur une ligne vide (
\n\n
), voici comment je le ferais dans ksh. Je ne l'ai pas testé, et ce n'est probablement pas idéal, mais quelque chose dans ce sens fonctionnerait:la source
\n\n
, je pense.\n\n
, mais plutôt ne pas se séparer au milieu d'une ligne. Il appelle une nouvelle ligne une ligne vierge.Essayer
awk
la source
Si vous ne vous souciez pas de l'ordre des enregistrements mais que vous êtes particulièrement soucieux d'obtenir un certain nombre de fichiers de sortie, la réponse de Stéphane est la voie que j'irais. Mais j'ai le sentiment que vous pourriez vous soucier davantage de spécifier une taille que chaque fichier de sortie ne doit pas dépasser. Cela le rend plus facile car vous pouvez lire votre fichier d'entrée et collecter des enregistrements jusqu'à ce que vous atteigniez cette taille, puis démarrer un nouveau fichier de sortie. Si cela fonctionne pour vous, la plupart des langages de programmation peuvent gérer votre tâche avec un court script. Voici une implémentation awk:
Placez-le dans un fichier, par exemple
program.awk
, et exécutez-le avecawk -v maxlen=10000 -f program.awk big_db.msg
où la valeur demaxlen
est le plus d'octets que vous souhaitez dans un fichier. Il utilisera 500k par défaut.Si vous souhaitez obtenir un nombre défini de fichiers, le moyen le plus simple consiste probablement à diviser simplement la taille de votre fichier d'entrée par le nombre de fichiers que vous souhaitez, puis à ajouter un peu à ce nombre pour obtenir
maxlen
. Par exemple, pour obtenir 15 fichiers de vos 8726593 octets, divisez par 15 pour obtenir 581773 et ajoutez-en, alors donnez peut-êtremaxlen=590000
oumaxlen=600000
. Si vous voulez le faire de façon répétée, il serait possible de configurer le programme pour le faire.la source