2017-07-12 1 views
0

J'ai un grand fichier de séquence avec 'Ç' comme délimiteur. Nous devons diviser à chaque 40 'Ç' dans une nouvelle ligne.Comment insérer n après chaque nième délimiteur sans "problème de mémoire" dans Bash

Nous avons essayé d'utiliser la commande perl/cut, mais nous obtenons "out of memory" erreur, parce que c'est un énorme fichier et la lecture/écriture arrive à la fois.

donc ce que je veux est la suivante

Cut à chaque occurrence 40e delimter et d'écriture/de chasse au fichier et non tenir en mémoire et à nouveau faire la même chose pour les 40 suivant et ainsi sur.

Est-ce réalisable dans Bash?

Toute aide serait grandement appréciée.

Edit:

Ceci est la commande que nous avons utilisé dans PERL

perl -pe 's{Ç}{++$n % 40 ? $& : "\n"}ge' <file_name> 

dire que les données sont les suivantes.

123ÇasfiÇsadfÇtest1Ç123ÇasfiÇsadfÇtest1ÇmockÇdataÇtest1Ç123ÇasfiÇsadfÇtest1ÇmockÇdata 

Je veux couper à (dire 3 delimiter à la nouvelle ligne) et assignez à une variable ou quelque chose et tirer la chasse au fichier de sorte que la mémoire est effacée.

Sortie prévue

123ÇasfiÇsadf 
test1Ç123Çasfi 
sadfÇtest1Çmock 

Note: Il est un énorme fichier de séquence. Nous sommes en mesure d'atteindre la sortie désirée avec la commande ci-dessus, mais pour un fichier plus volumineux, il lance une exception de mémoire et nous voulons donc vider les morceaux.

+0

Pourquoi est-ce marqué Java? –

+1

Je dirais même: [java] ou [bash ou [puthon]? x) – Nathan

+0

Désolé. Corrigé maintenant. –

Répondre

1

Il est un peu long, mais dire Perl pour traiter Ç en tant que séparateur d'enregistrement au lieu de \n; Vous pouvez ensuite joindre des "lignes" au fur et à mesure de leur lecture, les regrouper par lots et les afficher en groupes. (Mon Perl est rouillé, il y a probablement une façon plus simple de le faire.)

perl -ne 'BEGIN {$/="Ç"; $c=0; sub d { chomp $out; print "$out\n"; $out=""; $c=0; }} 
      $out .= $_; $c++; &d if $c == 3; 
      END { &d }' tmp.txt 

Au début du script, nous changeons $/ de sa valeur par défaut de votre nouvelle ligne à delimiter; maintenant une "ligne" est définie comme une chaîne se terminant par un Ç. Nous initialisons un compteur $c pour garder trace du nombre de lignes que nous avons lues, et nous définissons un sous-programme pour sortir les lignes accumulées dans une variable $out, puis réinitialiser l'accumulateur et le compteur.

Pour chaque ligne d'entrée, nous ajoutons d'abord cette ligne à l'accumulateur, incrémenterons le compteur, puis appellerons notre routine de sortie si la valeur du compteur atteint la taille de notre groupe cible.Enfin, nous appelons la routine de sortie à la fin de l'entrée pour vider toutes les lignes restantes dans l'accumulateur.

+0

Merci beaucoup Fonctionne comme un charme Serait génial si vous pouvez expliquer la commande un peu plus pour moi de comprendre.Merci à l'avance –

+0

Merci beaucoup. !! –

0

Si Python est une option, voici un port de mon projet de code C:

# -*- coding: latin1 -*- 
import sys 

def cvt(fdin, fdout, delim, count): 
    curr = count 
    while True: 
     c = fdin.read(1) 
     if c is None or c == '': break 
     if c == delim: 
      curr -= 1 
      if curr == 0: 
       curr = count 
       c = '\n' 
     dummy = fdout.write(c) 

cvt(sys.stdin, sys.stdout, 'Ç', 3) 

Il donne comme prévu:

echo "123ÇasfiÇsadfÇtest1Ç123ÇasfiÇsadfÇtest1ÇmockÇdataÇtest1Ç123ÇasfiÇsadfÇtest1ÇmockÇdata" | python ess.py 
123ÇasfiÇsadf 
test1Ç123Çasfi 
sadfÇtest1Çmock 
dataÇtest1Ç123 
asfiÇsadfÇtest1 
mockÇdata