J'essaie de comparer pour comparer deux façons différentes de traiter un fichier. J'ai une petite quantité de données d'entrée, mais pour obtenir de bonnes comparaisons, je dois répéter les tests plusieurs fois.
Plutôt que de simplement répéter les tests, je voudrais dupliquer les données d'entrée un certain nombre de fois (par exemple 1000) pour qu'un fichier de 3 lignes devienne 3000 lignes et je puisse exécuter un test beaucoup plus satisfaisant.
Je passe les données d'entrée via un nom de fichier:
mycommand input-data.txt
perl
c'est tellement efficace qu'il est conçu pour ça.Je pensais à l'origine que je devrais générer un fichier secondaire mais je pourrais simplement boucler le fichier d'origine dans Bash et utiliser une redirection pour le faire apparaître comme un fichier.
Il existe probablement une douzaine de façons différentes de faire la boucle, mais voici quatre:
La troisième méthode est improvisée à partir du commentaire de maru ci-dessous et construit une grande liste de noms de fichiers d'entrée pour cat.
xargs
divisera cela en autant d'arguments que le système le permettra. C'est beaucoup plus rapide que n chats séparés.La
awk
voie (inspirée de la réponse de terdon ) est probablement la plus optimisée mais elle duplique chaque ligne à la fois. Cela peut convenir ou non à une application particulière, mais c'est rapide et efficace.Mais cela génère à la volée. La sortie Bash est probablement beaucoup plus lente que ce que quelque chose peut lire, vous devez donc générer un nouveau fichier pour le test. Heureusement, ce n'est qu'une extension très simple:
la source
cat $(for i in {1..N}; do echo filename; done)
. Cela a la limitation de la taille d'argument, mais devrait être plus rapide.Voici une
awk
solution:C'est essentiellement aussi rapide que @ Gnuc's Perl (j'ai couru à la fois 1000 fois et j'ai obtenu le temps moyen):
la source
awk '{for(i=0; i<1000; i++)print}' input-data.txt
pour qu'il émette seulement 1000 copies de chaque ligne à la fois. Ne conviendra pas à toutes les occasions mais encore plus rapide, moins de retard et n'a pas besoin de conserver le fichier entier en RAM.123123123
était bien, mais ce111222333
n'était pas le cas. Votre version est nettement plus rapide que celle de Gnouc, elle s'établit en moyenne à 0.00297 secondes. EDIT: grattez ça, j'ai fait une erreur, c'est en fait équivalent à 0.004013 secondes.Je voudrais simplement utiliser un éditeur de texte.
Si vous devez absolument le faire via la ligne de commande (cela nécessite que vous ayez
vim
installé, car ilvi
n'a pas la:normal
commande), vous pouvez utiliser:Ici,
-es
(ou-e -s
) fait fonctionner vim silencieusement, donc il ne devrait pas prendre le contrôle de votre fenêtre de terminal, et l'-u NONE
empêche de regarder votre vimrc, ce qui devrait le faire fonctionner un peu plus vite qu'il ne le ferait autrement (peut-être beaucoup plus vite, si vous utilisez beaucoup de plugins vim).la source
Voici une simple ligne, sans script impliqué:
Explication
`yes input-data.txt | head -1000 | paste -s`
produit le texteinput-data.txt
1000 fois séparé par un espace blanccat
une liste de fichiersla source
xargs paste -s
? Cela fonctionne, mais ne préserve pas les sauts de ligne dans le fichier d'entrée.Tout en travaillant sur un script complètement différent, j'ai appris qu'avec 29 millions de lignes de texte, l'utilisation
seek()
et l'exploitation des données par octets sont souvent plus rapides que ligne par ligne. La même idée est appliquée dans le script ci-dessous: nous ouvrons le fichier, et au lieu de parcourir en boucle l'ouverture et la fermeture du fichier (ce qui peut ajouter des frais généraux, même si cela n'est pas significatif), nous gardons le fichier ouvert et cherchons au début.Le script lui-même est assez simple à utiliser:
Pour un fichier texte de 3 lignes et 1000 itérations, cela se passe très bien, environ 0,1 seconde:
Le script lui-même n'est pas le plus élégant, pourrait probablement être raccourci, mais fait le travail. Bien sûr, j'ai ajouté quelques bits supplémentaires ici et là, comme la
error_out()
fonction, ce qui n'est pas nécessaire - c'est juste une petite touche conviviale.la source
Nous pouvons résoudre ce problème sans fichier supplémentaire, ni programmes spéciaux, pur Bash (enfin, cat est une commande standard).
Sur la base d'une fonctionnalité de printf dans bash, nous pouvons générer une chaîne répétée):
Ensuite, nous pouvons envoyer une telle liste de 1000 noms de fichiers (répétés) et appeler cat:
Et enfin, nous pouvons donner la sortie à la commande à exécuter:
Ou, si la commande doit recevoir l'entrée dans le stdin:
Oui, le double <est nécessaire.
la source
Je générerais un nouveau fichier en utilisant Unix pour la boucle:
la source