web-dev-qa-db-fra.com

Comment utiliser sed pour supprimer les n dernières lignes d'un fichier

Je veux supprimer quelques lignes n à la fin d'un fichier. Cela peut-il être fait avec sed?

Par exemple, pour supprimer les lignes 2 à 4, je peux utiliser

$ sed '2,4d' file

Mais je ne connais pas les numéros de ligne. Je peux supprimer la dernière ligne en utilisant 

$sed $d file

mais je veux savoir comment supprimer n lignes à la fin. S'il vous plaît laissez-moi savoir comment faire cela en utilisant sed ou une autre méthode.

109
mezda

Je ne sais pas à propos de sed, mais cela peut être fait avec head:

head -n -2 myfile.txt
180
ams

Si le codage en dur n est une option, vous pouvez utiliser des appels séquentiels à sed. Par exemple, pour supprimer les trois dernières lignes, supprimez la dernière ligne trois fois:

sed '$d' file | sed '$d' | sed '$d'
24
Kyle

De la sed one-liners :

# delete the last 10 lines of a file
sed -e :a -e '$d;N;2,10ba' -e 'P;D'   # method 1
sed -n -e :a -e '1,10!{P;N;D;};N;ba'  # method 2

Semble être ce que vous recherchez.

22
qstebom

Une solution sed et tac amusante et simple:

n=4
tac file.txt | sed "1,$n{d}" | tac

REMARQUE

  • des guillemets doubles " sont nécessaires pour que le shell puisse évaluer la variable $n dans la commande sed. Entre guillemets simples, aucune interpolation ne sera effectuée.
  • tac est une cat inversée, voir man 1 tac
  • les {} dans sed sont là pour séparer $n & d (sinon, le Shell tente d'interpoler une variable $nd non existante)
20
Gilles Quenot

Utilisez sed, mais laissez le shell faire le calcul, l'objectif étant d'utiliser la commande d en donnant une plage (pour supprimer les 23 dernières lignes):

sed -i "$(($(wc -l < file)-22)),\$d" file

Pour supprimer les 3 dernières lignes, de l’intérieur vers l’extérieur:

$(wc -l < file)

Donne le nombre de lignes du fichier: dire 2196

Nous voulons supprimer les 23 dernières lignes, donc pour le côté gauche ou la plage:

$((2196-22))

Donne: 2174 Ainsi, l'interprétation originale de sed après Shell est la suivante:

sed -i 2174,$d file

Avec -i en cours de montage sur place, le fichier est maintenant 2173 lignes!

13
lzc

Vous pouvez utiliser head pour cela.

Utilisation 

$ head --lines=-N file > new_file

où N est le nombre de lignes que vous souhaitez supprimer du fichier.

Le contenu du fichier original moins les N dernières lignes est maintenant dans new_file

10
richard

Pour compléter, j’aimerais ajouter ma solution . J'ai fini par le faire avec la variable standard ed:

ed -s sometextfile <<< $'-2,$d\nwq'

Ceci supprime les 2 dernières lignes en utilisant l'édition sur place (bien que utilise utilise un fichier temporaire dans /tmp !!)

7
Michel

Pour tronquer des fichiers très volumineux réellement sur place, nous avons la commande truncate . Elle ne connaît pas les lignes, mais tail + wc peut convertir les lignes en octets:

file=bigone.log
lines=3
truncate -s -$(tail -$lines $file | wc -c) $file

Il existe une condition de concurrence évidente si le fichier est écrit en même temps . Dans ce cas, il peut être préférable d'utiliser head - il compte les octets à partir du début du fichier (mind disk IO), nous allons donc toujours tronquer limite de ligne (éventuellement plus de lignes que prévu si le fichier est écrit activement): 

truncate -s $(head -n -$lines $file | wc -c) $file

One-liner pratique si vous échouez lors de la tentative de connexion en mettant le mot de passe à la place du nom d'utilisateur:

truncate -s $(head -n -5 /var/log/secure | wc -c) /var/log/secure
5
Kamil Christ

Cela pourrait fonctionner pour vous (GNU sed):

sed ':a;$!N;1,4ba;P;$d;D' file
4
potong

La plupart des réponses ci-dessus semblent nécessiter des commandes/extensions GNU:

    $ head -n -2 myfile.txt
    -2: Badly formed number

Pour une solution légèrement plus portable:

     Perl -ne 'Push(@fifo,$_);print shift(@fifo) if @fifo > 10;'

OR

     Perl -ne 'Push(@buf,$_);END{print @buf[0 ... $#buf-10]}'

OR

     awk '{buf[NR-1]=$0;}END{ for ( i=0; i < (NR-10); i++){ print buf[i];} }'

Où "10" est "n".

2
DarkHeart

Avec les réponses ici, vous auriez déjà appris que sed n’est pas le meilleur outil pour cette application. 

Cependant, je pense qu’il ya un moyen de le faire en utilisant sed; L'idée est d'ajouter N lignes pour conserver l'espace jusqu'à ce que vous puissiez lire sans toucher EOF. Lorsque vous appuyez sur EOF, imprimez le contenu de l'espace de stockage et quittez.

sed -e '$!{N;N;N;N;N;N;H;}' -e x

La commande sed ci-dessus omettra les 5 dernières lignes.

2
Rishabh Sagar

Essayez la commande suivante:

n = line number
tail -r file_name | sed '1,nd' | tail -r
2
Rishav Kaushal

Cela peut être fait en 3 étapes:

a) Comptez le nombre de lignes du fichier que vous souhaitez modifier:

 n=`cat myfile |wc -l`

b) Soustrayez de ce nombre le nombre de lignes à supprimer:

 x=$((n-3))

c) Dites à sed de supprimer de ce numéro de ligne ($x) jusqu'à la fin:

 sed "$x,\$d" myfile
1
Rey Lefebvre

Vous pouvez obtenir le nombre total de lignes avec wc -l <file> et utiliser

head -n <total lines - lines to remove> <file>

1
SWW13

Cela supprimera les 12 dernières lignes

sed -n -e :a -e '1,10!{P;N;D;};N;ba'
0
R. Kumar

Pour supprimer les 4 dernières lignes:

$ nl -b a file | sort -k1,1nr | sed '1, 4 d' | sort -k1,1n | sed 's/^ *[0-9]*\t//'   
0
mstafreshi
sed -n ':pre
1,4 {N;b pre
    }
:cycle
$!{P;N;D;b cycle
  }' YourFile

version posix

0
NeronLeVelu

Je suis venu avec ceci, où n est le nombre de lignes que vous souhaitez supprimer:

count=`wc -l file`
lines=`expr "$count" - n`
head -n "$lines" file > temp.txt
mv temp.txt file
rm -f temp.txt

C'est un petit rond point, mais je pense que c'est facile à suivre.

  1. Compter le nombre de lignes dans le fichier principal
  2. Soustrayez le nombre de lignes que vous souhaitez supprimer du compte
  3. Imprimez le nombre de lignes que vous souhaitez conserver et stocker dans un fichier temporaire
  4. Remplacer le fichier principal par le fichier temporaire
  5. Supprimer le fichier temporaire
0
coyotetechy

Pour supprimer les N dernières lignes d’un fichier, vous pouvez utiliser le même concept de

$ sed '2,4d' file

Vous pouvez utiliser une commande combo avec queue pour inverser le fichier: si N vaut 5

$ tail -r file | sed '1,5d' file | tail -r > file

Et cette manière fonctionne aussi là où la commande head -n -5 file ne s’exécute pas (comme sur un mac!).

0
Alessandra Bilardi

Je préfère cette solution;

head -$(gcalctool -s $(cat file | wc -l)-N) file

Nest le nombre de lignes à supprimer.

0
p014k