Dans cette réponse ( comment supprimer la première ligne d'un fichier avec sed? ), Il existe deux façons de supprimer le premier enregistrement d'un fichier:
sed '1d' $file >> headerless.txt
** ---------------- OU ----------------**
tail -n +2 $file >> headerless.txt
Personnellement, je pense que l' tail
option est cosmétiquement plus agréable et plus lisible, mais probablement parce que je suis séduit.
Quelle méthode est la plus rapide?
sed
est plus portable: "+2" pourtail
fonctionne bien sur Ubuntu, qui utilise GNUtail
, mais ne fonctionnera pas sur BSDtail
.tail
manque de compatibilité multiplateforme.-n
option et utilisait la syntaxetail +2 $file
. Voir freebsd.org/cgi/… Il est possible que vous pensiez à cela plutôt qu'à l'un des BSD modernes.Réponses:
Performances de
sed
vstail
pour supprimer la première ligne d'un fichierTL; DR
sed
est très puissant et polyvalent, mais c'est ce qui le rend lent, en particulier pour les fichiers volumineux avec de nombreuses lignes.tail
fait juste une chose simple, mais celle-ci, elle le fait bien et rapidement, même pour des fichiers plus gros avec de nombreuses lignes.Pour les fichiers de petite et moyenne taille,
sed
ettail
fonctionnent de manière similaire rapidement (ou lentement, selon vos attentes). Cependant, pour les fichiers d'entrée plus volumineux (plusieurs Mo), la différence de performances augmente considérablement (un ordre de grandeur pour les fichiers de l'ordre de centaines de Mo), avec destail
performances nettement supérieuressed
.Expérience
Préparations générales:
Nos commandes à analyser sont:
Notez que je redirige la sortie à
/dev/null
chaque fois pour éliminer la sortie du terminal ou les écritures de fichier comme goulot d'étranglement des performances.Configurons un disque RAM pour éliminer les E / S disque comme goulot d'étranglement potentiel. J'ai personnellement un
tmpfs
monté à/tmp
donc j'ai simplement placé montestfile
là pour cette expérience.Ensuite, je crée une fois un fichier de test aléatoire contenant un nombre spécifié de lignes
$numoflines
avec une longueur de ligne aléatoire et des données aléatoires à l'aide de cette commande (notez que ce n'est certainement pas optimal, cela devient vraiment lent pour environ> 2 millions de lignes, mais peu importe, ce n'est pas le chose que nous analysons):Oh, au fait. mon ordinateur portable de test exécute Ubuntu 16.04, 64 bits sur un processeur Intel i5-6200U. Juste pour comparaison.
Timing de gros fichiers:
Mise en place d'un énorme
testfile
:L'exécution de la commande ci-dessus avec
numoflines=10000000
produit un fichier aléatoire contenant 10 millions de lignes, occupant un peu plus de 600 Mo - c'est assez énorme, mais commençons par cela, car nous pouvons:Effectuez la course chronométrée avec notre énorme
testfile
:Maintenant, faisons d'abord une seule exécution chronométrée avec les deux commandes pour estimer avec quelle ampleur nous travaillons.
On voit déjà un résultat vraiment clair pour les gros fichiers,
tail
c'est une amplitude plus rapide quesed
. Mais juste pour le plaisir et pour être sûr qu'il n'y a pas d'effets secondaires aléatoires qui font une grande différence, faisons-le 100 fois:La conclusion reste la même,
sed
est inefficace pour supprimer la première ligne d'un gros fichier,tail
doit y être utilisée.Et oui, je sais que les constructions de boucles de Bash sont lentes, mais nous ne faisons que relativement peu d'itérations ici et le temps qu'une boucle simple prend n'est pas significatif par rapport aux
sed
/tail
runtimes de toute façon.Timing de petits fichiers:
Mise en place d'un petit
testfile
:Maintenant, pour être complet, regardons le cas le plus courant où vous avez un petit fichier d'entrée dans la plage de Ko. Créons un fichier d'entrée aléatoire avec
numoflines=100
, ressemblant à ceci:Effectuez la course chronométrée avec notre petit
testfile
:Comme nous pouvons nous attendre à ce que le timing de ces petits fichiers soit de l'ordre de quelques millisecondes par expérience, faisons tout de suite 1000 itérations:
Comme vous pouvez le voir, les horaires sont assez similaires, il n'y a pas grand-chose à interpréter ou à s'interroger. Pour les petits fichiers, les deux outils sont tout aussi bien adaptés.
la source
awk
peut aussi le faire. Ma question d'origine était basée sur le lien que j'ai trouvé en premier lieu. Après tout votre travail acharné, veuillez indiquer si je dois supprimer enawk
tant que solution candidate et revenir à la portée du projet d'origine de seulementsed
ettail
.awk 'NR > 1'
, fait intéressant).Voici une autre alternative, en utilisant uniquement les commandes bash et
cat
:$file
est redirigé dans le{ }
groupe de commandes. Leread
lit simplement et rejette la première ligne. Le reste du flux est ensuite dirigé verscat
lequel l'écrit dans le fichier de destination.Sur mon Ubuntu 16.04, les performances et la
tail
solution sont très similaires. J'ai créé un fichier de test volumineux avecseq
:tail
Solution:cat
/ brace solution:Je n'ai cependant qu'une machine virtuelle Ubuntu à portée de main en ce moment, et j'ai vu des variations significatives dans le timing des deux, bien qu'elles soient toutes dans le même stade.
la source
tail
mais je pense toujours que l'read
option est très cool.En essayant mon système et en préfixant chaque commande avec,
time
j'ai obtenu les résultats suivants:sed:
et la queue:
ce qui suggère que, sur mon système au moins AMD FX 8250 exécutant Ubuntu 16.04, la queue est nettement plus rapide. Le fichier de test avait 10 000 lignes avec une taille de 540 Ko. Le fichier a été lu sur un disque dur.
la source
sed
peut jouer un rôle dans ce résultat, c'est l'ordre dans lequel vous les avez testés.sed
était environ deux fois plus rapide.Il n'y a pas de moyen objectif de dire ce qui est mieux, parce que
sed
ettail
ne sont pas les seules choses qui fonctionnent sur un système lors de l' exécution du programme. De nombreux facteurs tels que les E / S disque, les E / S réseau, les interruptions CPU pour les processus de priorité plus élevée - tous ces facteurs influencent la vitesse d'exécution de votre programme.Les deux sont écrits en C, donc ce n'est pas un problème de langue, mais plutôt un problème environnemental. Par exemple, j'ai un SSD et sur mon système, cela prendra du temps en microsecondes, mais pour le même fichier sur le disque dur, cela prendra plus de temps car les disques durs sont beaucoup plus lents. Le matériel joue donc également un rôle.
Il y a quelques choses que vous voudrez peut-être garder à l'esprit lorsque vous envisagerez la commande à choisir:
sed
est un éditeur de flux pour transformer du texte.tail
sert à produire des lignes de texte spécifiques. Si vous souhaitez traiter des lignes et les imprimer uniquement, utiliseztail
. Si vous souhaitez modifier le texte, utilisezsed
.tail
a une syntaxe beaucoup plus simple quesed
, alors utilisez ce que vous pouvez lire vous-même et ce que les autres peuvent lire.Un autre facteur important est la quantité de données que vous traitez. Les petits fichiers ne vous donneront aucune différence de performances. L'image devient intéressante lorsque vous traitez de gros fichiers. Avec un BIGFILE.txt de 2 Go, nous pouvons voir qu'il
sed
a beaucoup plus d'appels systèmetail
et s'exécute considérablement plus lentement.la source
tail
mieux quesed
- utilisez cela. Personnellement , j'utiliserpython
ouawk
plutôt quesed
parce qu'il peut devenir complexe. De plus, si vous êtes préoccupé par les performances, regardons la réalité - vous voyez des résultats en microsecondes ici. Vous ne sentirez pas de différence à moins qu'il s'agisse d'un énorme fichier de plage de gigaoctets que vous essayez de lireawk
réponse:) ... Ma question était basée sur un autre AU Q&A (dans le lien) et là, ils n'ont jamais mentionnéawk
. Je suis d'accord que le décalage horaire est nominal sur les petits fichiers. J'essayais juste de développer de bonnes habitudes.awk 'NR!=1' input_file.txt
. Cela me donne également le même résultat, environ 150 millisecondes, même nombre pourtail
etsed
. Mais agian, j'utilise SSD, donc je dirais que c'est le disque dur et le CPU qui importent, pas la commande.sed
prennent plus de 3 minutes, alors qu'iltail
ne faut que 20 secondes environ. Ce n'est pas si gros mais en fait, certainement pas dans la gamme GB.La meilleure réponse n'a pas pris en compte le disque
> /dev/null
si vous avez un gros fichier et que vous ne voulez pas créer de doublon temporaire sur votre disque, essayez
vim -c
Modifier: si le fichier est plus grand que la mémoire disponible
vim -c
ne fonctionne pas, il ne semble pas assez intelligent pour effectuer un chargement incrémentiel du fichierla source
D'autres réponses montrent bien ce qui est préférable de créer un nouveau fichier avec la première ligne manquante. Si vous souhaitez modifier un fichier plutôt que de créer un nouveau fichier, je parie que ce
ed
serait plus rapide car il ne devrait pas du tout créer un nouveau fichier. Mais vous devez rechercher comment supprimer une ligne aveced
car je ne l'ai utilisée qu'une seule fois.la source