Quelqu'un connaît-il un outil non basé sur la ligne pour rechercher / remplacer des chaînes "binaires" d'une manière quelque peu efficace en mémoire? Voir aussi cette question .
J'ai un fichier texte de + 2 Go que j'aimerais traiter de manière similaire à ce que cela semble faire:
sed -e 's/>\n/>/g'
Cela signifie que je souhaite supprimer toutes les nouvelles lignes qui se produisent après un >
, mais pas ailleurs, de sorte que cela soit exclu tr -d
.
Cette commande (que j'ai obtenue de la réponse à une question similaire ) échoue avec couldn't re-allocate memory
:
sed --unbuffered ':a;N;$!ba;s/>\n/>/g'
Alors, existe-t-il d'autres méthodes sans recourir à C? Je déteste Perl, mais je suis prêt à faire une exception dans ce cas :-)
Je ne sais pas avec certitude de caractère qui ne se produit pas dans les données, donc remplacement temporaire \n
par un autre caractère est quelque chose que j'aimerais éviter si possible.
Des bonnes idées, quelqu'un?
la source
--unbuffered
?--unbuffered
manque de mémoire$!
-il?$!
si c'est le cas. Je pense que cela aura besoin de BEAUCOUP de mémoire.sed
n'est pas l'outil approprié dans ce cas.Réponses:
C'est vraiment trivial en Perl, vous ne devriez pas le détester!
Explication
-i
: modifiez le fichier en place et créez une sauvegarde de l'original appeléfile.bak
. Si vous ne voulez pas de sauvegarde, utilisez simplement à laperl -i -pe
place.-pe
: lire le fichier d'entrée ligne par ligne et imprimer chaque ligne après avoir appliqué le script donné en-e
.s/>\n/>/
: la substitution, tout commesed
.Et voici une
awk
approche:la source
awk '{ORS=/>$/?"":"\n"}1'
':a;N;$!ba;s/>\n/>/g'
dans votre question, vous avez renoncé à votre droit de vous plaindre de la lisibilité! : Pfoo ? bar : baz
construction mais je ne pouvais pas la faire fonctionner.Une
perl
solution:Explication
s///
est utilisé pour la substitution de chaînes.(?<=>)
est le modèle de lookbehind.\n
correspond à la nouvelle ligne.Le motif entier signifie supprimer tous les sauts de ligne qui l'ont
>
précédé.la source
s/>\n/>/
?s/>\K\n//
fonctionnerait égalementQue dis-tu de ça:
Pour GNU sed, vous pouvez également essayer d'ajouter l' option
-u
(--unbuffered
) selon la question. GNU sed en est également satisfait en tant que simple doublure:la source
\n
si le fichier se termine>\n
, mais c'est probablement préférable de toute façon.}
doit-elle être dans une expression distincte? cela ne fonctionnera-t-il pas comme une expression multiligne?b loop\n}
ou-e 'b loop' -e '}'
mais pas aussib loop;}
et certainement pasb loop}
parce que}
et;
sont valides dans les noms d'étiquette (bien que personne de bon sens ne l'utiliserait. Et cela signifie que GNU sed n'est pas conforme à POSIX) et la}
commande doit être séparée de lab
commande.sed
est satisfait de tout ce qui précède même avec--posix
! La norme a également les éléments suivants pour les expressions d'accolade -The list of sed functions shall be surrounded by braces and separated by <newline>s
. Cela ne signifie-t-il pas que les points-virgules ne doivent être utilisés qu'en dehors des accolades?>
. L'original n'en a jamais eu, comme l'a souligné Stéphane.Vous devriez pouvoir l'utiliser
sed
avec laN
commande, mais l'astuce sera de supprimer une ligne de l'espace de motif chaque fois que vous en ajouterez une autre (de sorte que l'espace de motif ne contienne toujours que 2 lignes consécutives, au lieu d'essayer de lire dans son intégralité fichier) - essayezEDIT: après avoir relu le fameux Sed One-Liners de Peteris Krumins expliqué, je crois qu'une meilleure
sed
solution seraitqui ajoute seulement la ligne suivante dans le cas où il a déjà fait une
>
correspondance à la fin, et devrait boucler conditionnellement pour gérer le cas des lignes correspondantes consécutives (c'est le 39 de Krumin . Ajouter une ligne à la suivante si elle se termine par une barre oblique inverse) "\" à l' exception de la substitution de>
for\
comme caractère de jointure et du fait que le caractère de jointure est conservé dans la sortie).la source
>
(c'est aussi spécifique à GNU)sed
ne fournit pas un moyen d'émettre la sortie sans une nouvelle ligne finale. Votre approche utilisantN
fondamentalement fonctionne, mais stocke des lignes incomplètes en mémoire, et peut donc échouer si les lignes deviennent trop longues (les implants sed ne sont généralement pas conçus pour gérer des lignes extrêmement longues).Vous pouvez utiliser awk à la place.
Une autre approche consiste à
tr
remplacer le caractère de retour à la ligne par un caractère «ennuyeux» qui se produit fréquemment. L'espace peut fonctionner ici - choisissez un caractère qui a tendance à apparaître sur chaque ligne ou au moins une grande proportion de lignes dans vos données.la source
sed
ne fonctionne pas sans un tampon de 2,5 Go.tr
approche - mikeserv, vous avez publié une approche différente (valide, mais moins générique) qui se trouve également être utiliséetr
.qu'en est-il d'utiliser ed?
(via http://wiki.bash-hackers.org/howto/edit-ed )
la source
J'ai fini par utiliser gsar comme décrit dans cette réponse comme ceci:
la source
Il existe de nombreuses façons de le faire, et la plupart ici sont vraiment bonnes, mais je pense que celui-ci est mon préféré:
Ou même:
la source
*
. Dans l'état actuel des choses, il supprimera toutes les lignes vides suivant une ligne qui se termine par un>
. … Hmm. En repensant à la question, je vois que c'est un peu ambigu. La question dit: «Je veux supprimer tous les retours à la ligne qui se produisent après un>
,…» J'interprète cela comme signifiant que cela>\n\n\n\n\nfoo
devrait être changé en\n\n\n\nfoo
, mais je suppose que celafoo
pourrait être la sortie souhaitée.printf '>\n>\n\n>>\n>\n>>>\n>\nf\n\nff\n>\n' | tr '>\n' '\n>' | sed 's/^>*//;H;/./!d;x;y/\n>/>\n/'
- qui se traduit>>>>>>>>>>f\n\nff\n\n
pour moi avec la première réponse. Je suis curieux de savoir ce que vous faites pour le casser, car j'aimerais le réparer. Quant au deuxième point - je ne suis pas d'accord pour dire qu'il est ambigu. L'OP ne demande pas de supprimer tout ce qui>
précède une ligne\n
électronique, mais plutôt de supprimer toutes les\n
lignes électroniques suivant a>
.>\n\n\n\n\n
, seul le premier retour à la ligne est après a>
; tous les autres suivent d'autres nouveautés. Notez que la suggestion du PO «c'est ce que je veux, si seulement cela fonctionnait» ne l'étaitsed -e 's/>\n/>/g'
passed -e 's/>\n*/>/g'
.s/>\n/>/
sur>\n\n\n\n\n
serait encore quelque chose quis/>\n/>/
modifier Would.