web-dev-qa-db-fra.com

quel est le moyen le plus simple de supprimer la 1ère et la dernière ligne du fichier avec awk?

J'apprends awk/gawk. Si récemment, j’essaie simplement de résoudre tout problème avec celui-ci pour obtenir plus de possibilités de pratique.

Mon collègue a posé une question hier,

"comment supprimer la première et la dernière ligne du fichier"

. Je sais que sed '1d;$d' file fonctionnerait. aussi head/tail fonctionne aussi même si la performance est médiocre. Je lui ai dit le sed, il était heureux.

Plus tard, j'essayais d'écrire un awk one-liner: jusqu'ici, ce que j'ai obtenu est:

awk 'NR>1{a[++k]=$0}END{for(i=1;i<k;i++)print a[i]}'

Ceci stockera tout le fichier dans un tableau juste pour sauter la dernière ligne. Je pense qu'il devrait y avoir un moyen plus facile (ou meilleur) de le faire.

(s'il n'y a pas de moyen plus facile, plus rapide ou meilleur, je supprimerais la question)

je vous remercie.

17
Imagination

Cela fait le tour:

awk 'NR>2 {print last} {last=$0}'

awk exécute l'action print last uniquement lorsque NR> 2 (c'est-à-dire sur toutes les lignes sauf les 2 premières). Sur toutes les lignes, la variable last est définie sur la ligne actuelle. Ainsi, lorsque awk lit la troisième ligne, il affiche la ligne 2 (qui était stockée dans last). Lorsqu'il lit la dernière ligne (ligne n), il affiche le contenu de la ligne n-1. L’effet net est que les lignes 2 à n-1 sont imprimées.

46
William Pursell

Laissez-moi vous suggérer une autre solution. Si vous avez besoin d’un N personnalisé pour les lignes supérieure et inférieure, vous pouvez utiliser tail et head

awk '{print $1}'  | head -n -1 | tail -n+2

head -n -1 - supprime la dernière ligne

tail -n + 2 - commence la sortie de la deuxième ligne (supprime 1 ligne)

La commande suivante supprimera 3 lignes du haut et du bas:

awk '{print $1}'  | head -n -3 | tail -n +4

En fait, nous n'avons même pas besoin de awk ici:

more | head -n -1 | tail -n +2

ou 

cat | head -n -1 | tail -n +2

Merci à Igor Fobia pour le commentaire!

6
0x8BADF00D

Voici un autre moyen, mais cela nécessitait une longueur de fonction gawk:

awk '{firstline=2; cuttail=1; l[NR]=$0} END {for (i=firstline; i<=length(l)-cuttail; i++) print l[i]}'
2
Stanislav Korolev