web-dev-qa-db-fra.com

Queue inverse/tout imprimer sauf les dernières lignes?

Existe-t-il un moyen (ligne de commande POSIX) d’imprimer tout un fichier SAUF les n dernières lignes? Le cas d’utilisation étant, j’aurai plusieurs fichiers de taille inconnue, qui contiennent tous un pied de page standard de taille connue que je veux supprimer. Je me demandais s'il existait déjà un utilitaire qui le fait avant de l'écrire moi-même.

37
Tossrock

La plupart des versions de head (1) - GNU dérivé, en particulier, mais pas dérivé de BSD - ont une fonctionnalité permettant de le faire. Il montrera le haut du fichier sauf la fin si vous utilisez un nombre négatif pour le nombre de lignes à imprimer.

Ainsi:

head -n -10 textfile
39
Adam B

Probablement moins efficace que la méthode "wc" + "faire le calcul" + "queue", mais plus facile à regarder:

tail -r file.txt | tail +NUM | tail -r

NUM est égal à un de plus que le nombre de lignes de fin à supprimer, par exemple. +11 imprimera toutes les lignes sauf les 10 dernières. Cela fonctionne sur BSD qui ne supporte pas la syntaxe head -n -NUM.

10
user9645

L'utilitaire head est votre ami.

De la page de manuel de head:

-n, --lines=[-]K
     print the first K lines instead of the first 10;
       with the leading `-', print all but the last K lines of each file
6
Confusion

Il n'y a pas de commande standard pour le faire, mais vous pouvez utiliser awk ou sed pour remplir un tampon deNlignes et imprimer à partir de la tête une fois pleine. Par exemple. avec awk: 

awk -v n=5 '{if(NR>n) print a[NR%n]; a[NR%n]=$0}' file
4
geirha
cat <filename> | head -n -10 # Everything except last 10 lines of a file
cat <filename> | tail -n +10 # Everything except 1st 10 lines of a file
1
Siva Mandadi

C'est simple. Vous devez ajouter + au nombre de lignes que vous souhaitez éviter.

Cet exemple vous donne toutes les lignes sauf les 9 premières

tail -n +10 inputfile

(oui, pas les 10 premiers ... parce que ça compte différemment ... si vous voulez 10, tapez juste tail -n 11 inputfile)

0
user2836704

Si le pied de page commence par une ligne cohérente n'apparaissant pas ailleurs, vous pouvez utiliser sed:

sed '/FIRST_LINE_OF_FOOTER/q' filename

Cela imprime la première ligne du pied de page; si vous voulez éviter cela:

sed -n '/FIRST_LINE_OF_FOOTER/q;p' filename

Cela pourrait être plus robuste que de compter les lignes si la taille du pied de page change à l'avenir. (Ou il pourrait être moins robuste si la première ligne change.)

Une autre option, si la commande head de votre système ne prend pas en charge head -n -10, consiste à précalculer le nombre de lignes à afficher. Les éléments suivants dépendent de la syntaxe spécifique à bash:

lines=$(wc -l < filename) ; (( lines -= 10 )) ; head -$lines filename

Notez que la syntaxe head -NUMBER est prise en charge par certaines versions de head pour des raisons de compatibilité ascendante. POSIX n'autorise que la forme head -n NUMBER. De plus, POSIX n'autorise que l'argument à -n à être un entier décimal positif; head -n 0 n'est pas nécessairement un no-op.

Une solution compatible POSIX est:

lines=$(wc -l < filename) ; lines=$(($lines - 10)) ; head -n $lines filename

Si vous devez utiliser d'anciennes coques pré-POSIX, vous pouvez envisager ceci:

lines=`wc -l < filename` ; lines=`expr $lines - 10` ; head -n $lines filename

N'importe lequel d'entre eux pourrait faire des choses étranges si un fichier compte 10 lignes ou moins.

0
Keith Thompson

tac fichier.txt | queue + [n + 1] | tac

Cette réponse est similaire à celle de user9645, mais elle évite la commande tail -r, qui n'est également pas une option valide pour de nombreux systèmes. Voir, par exemple, https://ubuntuforums.org/showthread.php?t=1346596&s=4246c451162feff4e519ef2f5cb1a45f&p=8444785#post8444785 pour un exemple. 

Notez que le +1 (entre parenthèses) était nécessaire sur le système que je l’ai essayé, mais il n’est peut-être pas nécessaire sur votre système. Donc, pour supprimer la dernière ligne, je devais mettre 2 entre parenthèses. Cela est probablement lié au fait que la dernière ligne doit se terminer par un ou plusieurs caractères de saut de ligne réguliers. Ceci, sans doute, rend la dernière ligne une ligne vide. Si vous ne le faites pas, la commande tac combinera les deux dernières lignes. Par conséquent, la suppression de la "dernière" ligne (ou de la première à la fin de la commande) supprimera en réalité les deux dernières lignes.

Ma réponse devrait également être la solution la plus rapide parmi celles répertoriées à ce jour pour les systèmes ne disposant pas de la version améliorée de head. Je pense donc que c’est à la fois la réponse la plus robuste et la plus rapide.

0
Jason Arthur Taylor