Commande sed de base sur un gros fichier d'une ligne: impossible de réallouer la mémoire

10

J'ai un fichier texte de 250 Mo, le tout sur une seule ligne.

Dans ce fichier, je veux remplacer les acaractères par des bcaractères:

sed -e "s/a/b/g" < one-line-250-mb.txt

Il échoue avec:

sed: couldn't re-allocate memory

Il me semble que ce type de tâche pourrait être effectué en ligne sans allouer beaucoup de mémoire.
Existe-t-il un meilleur outil pour le travail ou une meilleure façon de l'utiliser sed?


GNU sed version 4.2.1
Ubuntu 12.04.2 LTS
1 Go de RAM

Nicolas Raoul
la source
4
Cette question concerne une expression multiligne très complexe. Ma question porte sur l'expression la plus élémentaire que vous puissiez imaginer.
Nicolas Raoul
@RubanSavvy plus, aucune des réponses sur l'autre Q ne prend en compte la longue ligne et en fait, les deux auraient probablement le même problème.
terdon
Pouvez-vous inclure votre version sed dans ce Q et aussi vos informations matérielles (RAM spécifiquement) et version distro?
slm

Réponses:

10

Oui, utilisez trplutôt:

tr 'a' 'b' < file.txt > output.txt

sedtraite en lignes de sorte qu'une énorme ligne lui causera des problèmes. Je m'attends à ce qu'il déclare une variable en interne pour contenir la ligne et votre entrée dépasse la taille maximale allouée à cette variable.

tr d'autre part traite des caractères et devrait être capable de gérer correctement les lignes arbitrairement longues.

terdon
la source
Curieusement, je viens de créer un fichier de 250 Mo rempli avec "abcabc ..." et j'ai pu le faire sed -e "s/a/z/g" b.txt > c.txtsans aucun problème. Utilisation de sed (GNU sed) 4.2.2.
slm
@slm même ici sur un fichier 496M et même sedversion, je suppose que cela dépend de l'implémentation ou du matériel.
terdon
Ouais, si je devais me demander si nous avons affaire à une ancienne version de sed.
slm
5

Les versions historiques de sed et awk avaient des problèmes de mémoire, ceux-ci ont principalement été corrigés dans des versions plus récentes, mais l'une des occurrences classiques de ce problème a frappé Larry Wall assez durement. sa réponse a été d'écrire un nouveau langage de programmation - sans limites de mémoire autres que le matériel. Il l'a appelé perl. votre problème spécifique peut être résolu plus simplement, mais la règle générale que j'utilise est lorsque sed n'utilisera pas perl.

Modifier: sur demande un exemple:

perl -pe "s/a/b/g" < one-line-250-mb.txt

ou pour une utilisation moindre de la mémoire:

perl -e 'BEGIN{$/=\32768}' -pe "s/a/b/g" < one-line-250-mb.txt
hildred
la source
1
Tout ce paragraphe se résume à "Perl.". Certains détails seraient bien, ou au moins un exemple ou quelque chose
Michael Mrozek
@MichaelMrozek Je me rends compte que la collection de chapeaux a tendance à conduire au roboedit, mais j'ai pensé avec votre réputation que vous y prêteriez un peu plus d'attention. Plus précisément, dans la mesure où le problème spécifique avait déjà été résolu, de manière très étroite, qui n’aiderait pas la majorité des personnes à effectuer des recherches, j’ai donc ajouté une réponse pour le cas général. la réponse élargie que j'ai fournie aurait aidé Nicolas Raoul S'il n'y avait pas déjà eu de solution viable, mais je doute qu'elle en aiderait beaucoup d'autres, alors que ma réponse originale aiderait tous ceux qui ont atteint les limites de sed. Si vous n'êtes pas d'accord, je supprimerai
hildred
@hildred Je ne pense pas que ce soit trop demander que vous puissiez supposer la bonne foi des modérateurs lorsqu'ils font des commentaires valides sur votre réponse, sans recourir immédiatement à des accusations d'arrière-pensées (chapeau, vraiment?!).
Chris Down
@ChrisDown Au contraire - je suis entièrement dedans pour les chapeaux. De plus, cela a été signalé comme non une réponse par plusieurs personnes, mais c'est une deuxième priorité éloignée pour les chapeaux
Michael Mrozek
Le deuxième avec la limitation de mémoire a fait l'affaire (pour mon fichier 1 ligne de 2,5 Go): merci! Un peu déçu sed, cependant. : \
Tomislav Nakic-Alfirevic