Il est possible de le faire avec d'autres outils, mais je voudrais savoir comment supprimer toutes les lignes du fichier, à l'exception des X dernières, à l'aide de la fonction sed
.
Réponses
Trop de publicités?En fait, vous imitez la queue. X = 20 dans cet exemple. L'exemple suivant supprimera toutes les lignes sauf les 20 dernières :
sed -i -e :a -e '$q;N;21,$D;ba' filename
Explication :
- L'option -e :a crée une étiquette appelée a
- Le -e suivant :
- $q - quitte et imprime l'espace du motif s'il s'agit de la dernière ligne
- N - ligne suivante
- 21,$D - exécute la commande "D" si le numéro de ligne est >= 21 (21,$ = 21ème ligne jusqu'à $ qui est la fin du fichier)
- ba - passe à l'étiquette 'a' qui est le début du script.
sed
est assez complexe lorsqu'il s'agit d'une tâche comme celle-ci. tail
, grep
ou awk
faciliterait grandement la tâche et devrait être utilisé à la place. Ceci étant dit, il est possible.
La solution suivante est adaptée de Recherche et remplacement en ligne et multiligne .
sed -ni '
# if the first line copy the pattern to the hold buffer
1h
# if not the first line then append the pattern to the hold buffer
1!H
# if the last line then ...
${
# copy from the hold to the pattern buffer
g
# delete current line if it is followed by at least X more lines
# replace X-1 with the proper value
s/.*\n\(\(.*\n\)\{X-1\}\)/\1/
# print
p
}
' filename
Sans les commentaires, il s'agit d'une belle phrase. Si vous voulez éliminer, par exemple, tout ce qui n'est pas les dix dernières lignes, utilisez ceci :
sed -ni '1h;1!H;${;g;s/.*\n\(\(.*\n\)\{9\}\)/\1/;p;}' filename
Basé sur le script en section 4.13 du manuel sed vous pourriez faire quelque chose comme ça :
n=10
(( n > 1 )) && script='1h; 2,'$n'{H;g;}; $q; 1,'$((n-1))'d; N; D'
(( n > 1 )) || script='$!d'
sed -i "$script" infile
Tac|sed|tac>&&(mv||cat>)
Les deux extraits de commande suivants supprimeront effectivement toutes les données, à l'exception de celles qui se trouvent à l'extrême droite de l'écran. dernier 5 lignes de ~/file1
. Si vous souhaitez conserver le dernier 10 lignes Vous pouvez les remplacer par d'autres : |sed '1,5!d;'
con |sed '1,10!d;'
, et ainsi de suite comme vous l'entendez.
-
tac ~/"file1" |sed '1,5!d;' |tac >"/tmp/file2" &&mv "/tmp/file2" ~/"file1"
-
tac ~/"file1" |sed '1,5!d;' |tac >"/tmp/file2" &&cat "/tmp/file2" >~/"file1"